I need to run React in production mode, which presumably entails defining the following somewhere in the enviornment:
process.env.NODE_ENV = 'production';
The issue is that I'm running this behind Tornado (a python web-server), not Node.js. I also use Supervisord to manage the tornado instances, so it's not abundantly clear how to set this in the running environment.
I do however use Gulp to build my jsx files to javascript.
Is it possible to somehow set this inside Gulp? And if so, how do I check that React is running in production mode?
Here is my Gulpfile.js:
'use strict'; var gulp = require('gulp'), babelify = require('babelify'), browserify = require('browserify'), browserSync = require('browser-sync'), source = require('vinyl-source-stream'), uglify = require('gulp-uglify'), buffer = require('vinyl-buffer'); var vendors = [ 'react', 'react-bootstrap', 'jquery', ]; gulp.task('vendors', function () { var stream = browserify({ debug: false, require: vendors }); stream.bundle() .pipe(source('vendors.min.js')) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('build/js')); return stream; }); gulp.task('app', function () { var stream = browserify({ entries: ['./app/app.jsx'], transform: [babelify], debug: false, extensions: ['.jsx'], fullPaths: false }); vendors.forEach(function(vendor) { stream.external(vendor); }); return stream.bundle() .pipe(source('build.min.js')) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('build/js')); }); gulp.task('watch', [], function () { // gulp.watch(['./app/**/*.jsx'], ['app', browserSync.reload]); gulp.watch(['./app/**/*.jsx'], ['app']); }); gulp.task('browsersync',['vendors','app'], function () { browserSync({ server: { baseDir: './', }, notify: false, browser: ["google chrome"] }); }); gulp.task('default',['browsersync','watch'], function() {});
ReactJs is one of the most trending Javascript libraries open-sourced by Facebook for creating fluent apps. ReactJs makes most of ECMAScript6 specification and hence the need for transforming the code into something that can run across browsers/devices, this is where Gulp comes to the rescue.
The production build creates minified bundles, lighter-weight source maps, and optimized assets. This improves the load time. React recommends using production mode while deploying the react app. We now know that production build helps in optimizing performance.
Step I: Add the following to your gulpfile.js somewhere
gulp.task('apply-prod-environment', function() { process.env.NODE_ENV = 'production'; });
Step II: Add it to your default task (or whichever task you use to serve/build your app)
// before: // gulp.task('default',['browsersync','watch'], function() {}); // after: gulp.task('default',['apply-prod-environment', 'browsersync','watch'], function() {});
OPTIONAL: If you want to be ABSOLUTELY CERTAIN that you are in prod mode, you can create the following slightly enhanced task instead of the one in Step I:
gulp.task('apply-prod-environment', function() { process.stdout.write("Setting NODE_ENV to 'production'" + "\n"); process.env.NODE_ENV = 'production'; if (process.env.NODE_ENV != 'production') { throw new Error("Failed to set NODE_ENV to production!!!!"); } else { process.stdout.write("Successfully set NODE_ENV to production" + "\n"); } });
Which will throw the following error if NODE_ENV is ever not set to 'production'
[13:55:24] Starting 'apply-prod-environment'... [13:55:24] 'apply-prod-environment' errored after 77 μs [13:55:24] Error: Failed to set NODE_ENV to production!!!!
Similar to the other answers, but hopefully gives someone a starting point:
var vendorList = ['react', 'react-dom']; gulp.task('vendor-dev', function() { browserify() .require(vendorList) .bundle() .on('error', handleErrors) .pipe(source('vendor.js')) .pipe(gulp.dest('./build/dev/js')); }); gulp.task('vendor-production', function() { process.env.NODE_ENV = 'production'; browserify() .require(vendorList) .bundle() .on('error', handleErrors) .pipe(source('vendor.js')) .pipe(buffer()) .pipe(uglify({ mangle: false })) .pipe(gulp.dest('./build/production/js')); });
The main difference is I am explicitly setting the NODE_ENV prior to bundling the vendor libraries. Gulp tasks aren't guaranteed to run in order.
Am I running in production mode?
If you remove the uglify line (and prior buffer) you will notice that both the dev and production builds are near identical in size - and match in line count.
The difference is the production version will be littered with:
"production" !== "production" ? [show dev error] : [no nothing]
Most reputable minify'ers (I believe) will strip out deadend code, such as the above, which will always result in false.
But really how do I tell?
Easiest method to be sure, would be goto the console of your running application and type:
React.createClass.toString();
The output should be:
"function (e){var t=function(e,t,n){this.__reactAutoBindMap&&c(this),"[....and more and more]
If you find the createClass in the react source, you will see:
createClass: function (spec) { var Constructor = function (props, context, updater) { // This constructor is overridden by mocks. The argument is used // by mocks to assert on what gets mounted. if ("production" !== 'production') { "production" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: react-legacyfactory') : undefined; } // Wire up auto-binding if (this.__reactAutoBindMap) { bindAutoBindMethods(this); }
Notice how the console output skips straight through to this.__reactAutobind
, because you are running in production mode, and using an minify'er, all the !== 'production' warngins and checks have been skipped over.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With