How to set React to production mode when using Gulp

后端 未结 5 1812
盖世英雄少女心
盖世英雄少女心 2021-02-03 20:36

I need to run React in production mode, which presumably entails defining the following somewhere in the enviornment:

process.env.NODE_ENV = \'production\';


        
相关标签:
5条回答
  • 2021-02-03 20:54

    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.

    0 讨论(0)
  • 2021-02-03 21:00

    Unfortunately none of the above answers work, because setting process.env.NODE_ENV has no effect in Browserify. The resulting bundle still has process.env.NODE_ENV references in it and hence

    • Browserify will not require() the React production version modules,
    • the minifier will not be able to remove dead code, and
    • the application will still be running in debug mode.

    This is unfortunately not the only place where this approach is offered as the correct answer :-(


    The correct approach can be found in e.g.

    • https://github.com/hughsk/envify/issues/15#issuecomment-62229101
    • https://reactjs.org/docs/optimizing-performance.html#browserify

    You need to switch the envify transform to be a global one, e.g.

    # note the "-g" instead of the usual "-t"
    $ browserify ... -g [ envify --NODE_ENV production ] ....
    

    or in gulpfile.js

    browserify(...)
        ...
        .transform('envify', {
            global:   true, // also apply to node_modules
            NODE_ENV: debug ? 'development' : 'production',
        })
        ...
        .bundle()
        ...
        .pipe(gulpif(!debug, babelMinify())) // my example uses gulp-babel-minify
        ...
    
    0 讨论(0)
  • 2021-02-03 21:02

    2017 - Edit: anyone trying to set up React in Gulp for a new project: Just use create-react-app


    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!!!!
    
    0 讨论(0)
  • 2021-02-03 21:04

    To set React in production mode you need to set your NODE_ENV variable to production and uglify your JS as an extra step.

    You're already taking care of the uglification, for setting your NODE_ENV variable :

    • Set the variable while running the gulp task :

    NODE_ENV='production' gulp

    • OR set it from inside your gulpfile by doing something like this :

    gulp.task('set-production-env', function() { return process.env.NODE_ENV = 'production'; });

    0 讨论(0)
  • 2021-02-03 21:19

    Also you may use handy way with gulp-environments:

    var environments = require('gulp-environments');
    
    var production = environments.production;
    
    gulp.src(paths.js)
        .pipe(concat("app.js"))
        // only minify the compiled JS in production mode
        .pipe(production(uglify()))
        .pipe(gulp.dest("./public/app/js/"));
    

    To run gulp in production mode:

    gulp build --env=production
    
    0 讨论(0)
提交回复
热议问题