React + Gulp + Babelify - node.js

I am trying to convert my working app from React and Gulp with ES5 to React + Gulp and ES6.
I only tried to replace reactify with babelify but i am still getting gulp error: Illegal import declaration
Here is my gulpfile.js:
"use strict";
var gulp = require('gulp');
var connect = require('gulp-connect'); //Runs a local dev server
var open = require('gulp-open'); //Open a URL in a web browser
var browserify = require('browserify'); // Bundles JS
var source = require('vinyl-source-stream'); // Use conventional text streams with Gulp
var concat = require('gulp-concat'); //Concatenates files
var lint = require('gulp-eslint'); //Lint JS files, including JSX
var babelify = require("babelify");
var config = {
port: 9005,
devBaseUrl: 'http://localhost',
paths: {
html: './src/*.html',
js: './src/**/*.js',
css: [
'node_modules/bootstrap/dist/css/bootstrap.min.css',
'node_modules/bootstrap/dist/css/bootstrap-theme.min.css',
'node_modules/toastr/toastr.css'
],
dist: './dist',
mainJs: './src/main.js'
}
}
//Start a local development server
gulp.task('connect', function() {
connect.server({
root: ['dist'],
port: config.port,
base: config.devBaseUrl,
livereload: true
});
});
gulp.task('open', ['connect'], function() {
gulp.src('dist/index.html')
.pipe(open({ uri: config.devBaseUrl + ':' + config.port + '/'}));
});
gulp.task('html', function() {
gulp.src(config.paths.html)
.pipe(gulp.dest(config.paths.dist))
.pipe(connect.reload());
});
gulp.task('js', function() {
browserify(config.paths.mainJs)
.transform(babelify)
.bundle()
.on('error', console.error.bind(console))
.pipe(source('bundle.js'))
.pipe(gulp.dest(config.paths.dist + '/scripts'))
.pipe(connect.reload());
});
gulp.task('css', function() {
gulp.src(config.paths.css)
.pipe(concat('bundle.css'))
.pipe(gulp.dest(config.paths.dist + '/css'));
});
gulp.task('lint', function() {
return gulp.src(config.paths.js)
.pipe(lint({config: 'eslint.config.json'}))
.pipe(lint.format());
});
gulp.task('watch', function() {
gulp.watch(config.paths.html, ['html']);
gulp.watch(config.paths.js, ['js', 'lint']);
});
gulp.task('default', ['html', 'js', 'css', 'lint', 'open', 'watch']);
and this is my js file (main.js):
"use strict";
var React = require('react');
var Router = require('react-router');
var routes = require('./routes');
import React from 'react';
Router.run(routes, function(Handler) {
React.render(<Handler/>, document.getElementById('app'));
});
Thanks a lot

You need to install babel preset
npm i babel-preset-es2015 --save-dev
and add config to .babelrc like this
{
"presets": [
"es2015"
]
}
Or it's better to use gulp-babel
$ npm install --save-dev gulp-babel babel-preset-es2015
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('default', () => {
return gulp.src('src/app.js')
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest('dist'));
});
https://www.npmjs.com/package/gulp-babel

Related

How to run and pack external executable using Electron?

For example, I have a compiled binary cudaDeviceQuery which returns a list of devices as JSON. Here's a piece of code:
export default function cudaDeviceQuery(): Promise<CollectorResponse> {
const throwError = () => {
throw new Error("Unfortunately your platform isn't yet unsupported");
};
const file = __DARWIN__
? path.join(__dirname, 'darwin', 'cudaDeviceQuery')
: __WIN32__
? path.join(__dirname, 'win', 'cudaDeviceQuery.exe')
: throwError();
const descriptor = spawn(file);
return new Promise((resolve, reject) => {
let outerData = '';
descriptor.stdout.on('data', data => {
outerData += data;
});
descriptor.on('close', () => {
try {
resolve(JSON.parse(outerData));
} catch (e) {
reject(e);
}
});
});
}
But when I use this function from renderer process __dirname is /, so I get spawn /darwin/cudaDeviceQuery ENOENT error. What's proper way to spawn it in dev envivroment and pack it in production?
A webpack config:
webpack.config.base.js:
/**
* Base webpack config used across other specific configs
*/
const webpack = require('webpack');
const path = require('path');
const getReplacements = require('./app/app-info').getReplacements;
const { dependencies: externals } = require('./app/renderer/package.json');
module.exports = {
module: {
noParse: [path.join(__dirname, 'node_modules/ws')],
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'babel-loader',
},
{
loader: 'ts-loader',
},
],
exclude: /node_modules/,
},
],
},
output: {
path: path.join(__dirname, 'app', 'renderer'),
filename: 'bundle.js',
libraryTarget: 'commonjs2',
},
// https://webpack.github.io/docs/configuration.html#resolve
resolve: {
extensions: ['.js', '.ts', '.tsx', 'json'],
modules: [path.join(__dirname, 'app', 'renderer'), 'node_modules'],
},
plugins: [new webpack.DefinePlugin(getReplacements())],
externals: [...Object.keys(externals || {}), 'ws'],
};
webpack.config.development.js:
/**
* Build config for development process that uses Hot-Module-Replacement
* https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
*/
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');
const getReplacements = require('./app/app-info').getReplacements;
const port = process.env.PORT || 3000;
module.exports = merge(baseConfig, {
devtool: 'inline-source-map',
entry: [
'react-hot-loader/patch',
`webpack-hot-middleware/client?path=http://localhost:${port}/__webpack_hmr&reload=true`,
'./app/renderer/index',
],
output: {
publicPath: `http://localhost:${port}/dist/`,
},
module: {
rules: [
// Css, SCSS, woff loaders are here
],
},
plugins: [
// https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
new webpack.HotModuleReplacementPlugin(),
new webpack.LoaderOptionsPlugin({
debug: true,
}),
],
// https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
target: 'electron-renderer',
});
webpack.config.electron.js:
/**
* Build config for electron 'Main Process' file
*/
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');
const getReplacements = require('./app/app-info').getReplacements;
module.exports = merge(baseConfig, {
devtool: 'source-map',
entry: ['./app/main/index.ts'],
// 'main.js' in root
output: {
path: __dirname,
filename: './app/main/main.js',
},
plugins: [
// Add source map support for stack traces in node
// https://github.com/evanw/node-source-map-support
// new webpack.BannerPlugin(
// 'require("source-map-support").install();',
// { raw: true, entryOnly: false }
// ),
],
/**
* Set target to Electron specific node.js env.
* https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
*/
target: 'electron-main',
/**
* Disables webpack processing of __dirname and __filename.
* If you run the bundle in node.js it falls back to these values of node.js.
* https://github.com/webpack/webpack/issues/2010
*/
node: {
__dirname: false,
__filename: false
},
});
As you see, I'm using dev server for hot module replacement, so maybe that is reason of this... I have server.js which create server with scripts and then I use it from main process. Here's server.js:
/**
* Setup and run the development server for Hot-Module-Replacement
* https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
*/
const argv = require('minimist')(process.argv.slice(2));
const { spawn } = require('child_process');
async function createMiddleware(port, configPath) {
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const config = require(configPath);
const app = express();
const compiler = webpack(config);
const PORT = process.env.PORT || port;
const wdm = webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
stats: {
colors: true,
},
});
app.use(wdm);
app.use(webpackHotMiddleware(compiler));
const server = app.listen(PORT, serverError => {
if (serverError) {
return console.error(serverError);
}
console.log(`Listening at http://localhost:${PORT}`);
});
process.on('SIGTERM', () => {
console.log('Stopping dev server');
wdm.close();
server.close(() => {
process.exit(0);
});
});
}
createMiddleware(3000, './webpack.config.development'); // A main renderer process
createMiddleware(3010, './webpack.config.server'); // A backend for communicating between renderer and remote server
if (argv['start-hot']) {
spawn('npm', ['run', 'start-hot'], {
shell: true,
env: process.env,
stdio: 'inherit',
})
.on('close', code => process.exit(code))
.on('error', spawnError => console.error(spawnError));
}
Another words, I need to call cudaDeviceQuery library from electron renderer process. I'm using a electron-builder but it doesn't matter, I can switch to another builder.
There are two things. If you set __dirname: true in your web app config you will get the relative path of the file from your context directory
If you set __dirname: false then __dirname will have the full path.
Development Mode
You have two options
Set __dirname: true and concatenate it with os.cwd()
Set __dirname: false and use __dirname directly
Production Mode
Set __dirname: true and use os.cwd().
Set __dirname: true and use process.resourcePath
I will prefer 2 as the preferred approach in production
Add this in package.json:
"scripts": {
"start": "electron .", "install": "electron-rebuild",
"package-osx": "electron-packager . Node-RED --platform=darwin --arch=x64 -- out=build --overwrite",
"package-mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --prune=true --out=release-builds",
"package-win": "electron-packager . electron-serialport --overwrite --asar=true --platform=win32 --arch=x64 --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"CryptoApp\"",
"package-linux": "electron-packager . electron-serialport --overwrite --asar=true --platform=linux --arch=x64 --prune=true --out=release-builds"
},
"dependencies": {
"electron-packager": "^12.1.0",
"electron-prebuilt": "^1.4.13",
}
In case of not working for windows use the following:
"package-win": "electron-packager . electron-serialport --overwrite --asar=true --platform=win32 --arch=ia32 --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"CryptoApp\"",
Thanks...

How to pass process.env.NODE_ENV from Gulp to Webpack?

I have a gulpfile, where I create a webpackDevServer to live-update my js code. I set a process.env.NODE_ENV variable in gulpfile, but for some reason webpack doesn't see it - it is undefined.
Here's the relevant piece of my gulpfile.js:
gulp.task("watch", ["_set-env:dev"], function() {
// modify default webpack configuration for Development Server
var webpackDevConfig = Object.create(webpackConfig);
webpackDevConfig.devtool = "eval";
webpackDevConfig.debug = "true";
new webpackDevServer(webpack(webpackDevConfig), {
proxy: {
"/api/*": {target: "http://localhost:8000", secure: false},
"/static/*": {target: "http://localhost:8000", secure: false},
"/media/*": {target: "http://localhost:8000", secure: false}
}
}).listen(8001, "localhost", function (err) {
if (err) throw new gutil.PluginError("webpack-dev-server", err);
gutil.log("[webpack-dev-server]", "http://localhost:8001" + webpackDevConfig.output.publicPath);
});
});
gulp.task("_set-env:dev", function() {
gutil.log("set-env", "ENV => development");
genv({
vars: {
NODE_ENV: "development"
}
});
});
Then in webpack I check its value and it is undefined:
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
...
const environmentsFile = path.join(__dirname, "/environments.json");
const nodeModulesPath = path.join(__dirname, "/node_modules");
const bowerComponentsPath = path.join(__dirname, "/bower_components");
console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
console.log(process.env.NODE_ENV);
const webpackConfig = {
entry: {
app: ["app.js"]
},
And on the console I see:
$ gulp watch
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
undefined
[22:28:34] Using gulpfile ~/Documents/frontend/gulpfile.js
[22:28:34] Starting '_set-env:dev'...
[22:28:34] set-env ENV => development
[22:28:34] Finished '_set-env:dev' after 7.63 ms
[22:28:34] Starting 'watch'...
You probably have something like this close to the top of your gulpfile:
var webpackConfig = require('./webpack.config.js');
That means your webpack configuration is evaluated before the _set-env:dev task even runs. Remember: your gulpfile only defines tasks. The tasks themselves aren't run until after the entire gulpfile has been evaluated.
You need to defer requiring your webpack configuration until after the _set-env:dev task has run by deleting the line at the top of your gulpfile and putting the require() directly into your watch task:
gulp.task("watch", ["_set-env:dev"], function() {
// modify default webpack configuration for Development Server
var webpackDevConfig = Object.create(require('./webpack.config.js'));

Hapijs-react-views setup

I'm finding some difficulties to follow the guide for hapijs-react-views package setup (npm hapi-js-react-views).
I can run the server but I only get this error on localhost:3000
{"statusCode":500,"error":"Internal Server Error","message":"An internal server error occurred"}
My repo on github is: hapi-react GitHub
My code is:
-routes
--index.js
-views
--index.jsx
-app.js
-package.js
// routes/index.js
exports.index = function(request, reply){
reply.view('index', { name: 'John' });
};
// views/index.js
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
module.exports = HelloMessage;
//app.js
var hapi = require('hapi');
var vision = require('vision');
var path = require('path');
var engine = require('hapijs-react-views')();
// Create a server with a host and port
var server = new hapi.Server();
server.connection({
host: 'localhost',
port: 3000
});
// Register Hapi plugins
server.register(vision, function (err) {
if(err) throw err;
});
var options = { jsx: { harmony: true } };
server.views({
defaultExtension: 'jsx',
engines: {
jsx: require('hapijs-react-views')(options), // support for .jsx files
js: require('hapijs-react-views')(options) // support for .js
},
relativeTo: __dirname,
path: 'views'
});
// Add the route
server.route({
method: 'GET',
path: '/',
config: {
handler: require('./routes').index
}
});
// Start the server
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
//package.json
"dependencies": {
"hapi": "^13.4.1",
"hapijs-react-views": "^0.7.3",
"react": "^15.1.0",
"vision": "^4.1.0"
}
Can you help me?
Thanks in advance.
For anyone who sees this in the future, there's a working example of jsx rendering with vision here: https://github.com/hapijs/vision/tree/master/examples/jsx
I was having this exact issue. The documentation doesn't say but you still require React in your view files. That fixed the problem for me.

Gulp-nodemon and watch task

I'm trying to create my build flow using gulp and nodemon. The objective is to watch sass files and compile them to css, and also restart node application when server file changes.
My gulpfile.js:
gulp.task('sass', function(){
return gulp.src(sassFilesTobeProcessed).
pipe(sass()).
pipe(concat('ready_stylesheet.css')).
pipe(gulp.dest('express/public/stylesheets'))
})
gulp.task('watch', function(){
return gulp.watch(allSassFiles, ['sass']);
})
gulp.task('serve', function(){
return nodemon({
script: 'express/app.js',
}).on('start', ['watch'])
.on('change', ['watch'])
.on('restart', function(){
console.log('restarted');
})
})
The watch task is working fine, files are compiled after change. But changes in my app.js server file doesn't trigger server restart. When I comment the .on statements it starts to work fine (server reloads), but then of course sass files are no longer observed. I assume hence, there is some conflict between these two, which I cannot discover. Appreciate any help! My OS - Windows 7, node 4.2.6, nodemon 1.9.1
Use a task dependency instead of .on(event) to start your watch task:
gulp.task('serve', ['watch'], function(){
return nodemon({
script: 'express/app.js',
})
.on('restart', function(){
console.log('restarted');
})
})
emit the restart event with nodemon
const cfg = require('../config')
const gulp = require('gulp')
const nodemon = require('nodemon')
const gnodemon = require('gulp-nodemon')
gulp.task('nodemon', ['ts', 'json'], () => {
gnodemon({
script: cfg.paths.main,
tasks: ['ts', 'json'],
ext: 'js',
watch: [cfg.paths.src],
// para no alterar el entorno de prodicion con test
env: {'NODE_ENV': process.env.NODE_ENV !== 'production'
? process.env.NODE_ENV || 'development' : 'development'}
})
.on('start', ['mocha'])
})
gulp.task('default', ['nodemon'], () => {
gulp.watch(cfg.paths.src, (event) => nodemon.emit('restart'))
})

RequireJs Module in node always returns undefined when using in a grunt task

I've a small config file that I need in frontend and in my grunt task.
js/config.js:
define(function() {
return [
{
id: 'demo',
displayName: 'Demo'
}
];
});
I can load the file in frontend without problems it also work in node.
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
var config = requirejs('config')
But when I try to load the same file in a grunt task it returns undefined:
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
grunt.registerTask('lala', function () {
var config = requirejs('config')
});
The problem was that the I require requireJs outside of the module.exports function. So this works after all:
module.exports = function(grunt) {
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js/cfe/app/platforms/as'
});
grunt.registerTask('lala', function () {
var config = requirejs('config')
});
}
This code works for me. First I've installed requirejs:
cd /path/to/code/directory
npm install requirejs
Then in my app.js:
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
var config = requirejs('config');
console.log(config);
And in the js/config.js:
define(function() {
return [
{
id: 'demo',
displayName: 'Demo'
}
];
});
When I run it, I get the correct result:
$ node app.js
[ { id: 'demo', displayName: 'Demo' } ]
I'm using Node v0.10.1.

Resources