简体   繁体   English

如何在使用Gulp时将React设置为生产模式

[英]How to set React to production mode when using Gulp

I need to run React in production mode, which presumably entails defining the following somewhere in the enviornment: 我需要在生产模式下运行React,这可能需要在环境中的某个地方定义以下内容:

process.env.NODE_ENV = 'production';

The issue is that I'm running this behind Tornado (a python web-server), not Node.js. 问题是我在Tornado(一个python web-server)后面运行它,而不是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. 我还使用Supervisord来管理龙卷风实例,所以在运行环境中如何设置它并不是很清楚。

I do however use Gulp to build my jsx files to javascript. 但是我使用Gulp将我的jsx文件构建为javascript。

Is it possible to somehow set this inside Gulp? 是否有可能以某种方式在Gulp中设置这个? And if so, how do I check that React is running in production mode? 如果是这样,我如何检查React是否在生产模式下运行?

Here is my Gulpfile.js: 这是我的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() {});

2017 - Edit: anyone trying to set up React in Gulp for a new project: Just use create-react-app 2017年 - 编辑:任何人都试图在Gulp中为一个新项目设置React:只需使用create-react-app


Step I: Add the following to your gulpfile.js somewhere 第一步:将以下内容添加到gulpfile.js中

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: 可选:如果您想要绝对禁止您处于产品模式,则可以创建以下略微增强的任务,而不是步骤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' 如果NODE_ENV未设置为“生产”,则会抛出以下错误

[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. 主要区别在于我在捆绑供应商库之前明确设置了NODE_ENV。 Gulp tasks aren't guaranteed to run in order. Gulp任务不能保证按顺序运行。

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. 如果删除uglify行(和之前的缓冲区),您会注意到dev和production构建的大小几乎相同 - 并且与行计数相匹配。

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. 大多数声誉良好的minify'ers(我相信)会删除deadend代码,如上所述,这将总是导致错误。

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: 如果在react源中找到createClass,您将看到:

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. 注意控制台输出如何直接跳到this.__reactAutobind ,因为你在生产模式下运行,并且使用minify'er,所有的!=='production'warngins和check都被跳过了。

To set React in production mode you need to set your NODE_ENV variable to production and uglify your JS as an extra step. 要在生产模式下设置React,您需要将NODE_ENV变量设置为production并将JS作为额外步骤进行uglify。

You're already taking care of the uglification, for setting your NODE_ENV variable : 您已经在处理uglification,用于设置NODE_ENV变量:

  • Set the variable while running the gulp task : 在运行gulp任务时设置变量:

NODE_ENV='production' gulp

  • OR set it from inside your gulpfile by doing something like this : 或者通过执行以下操作从gulpfile中设置它:

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

Also you may use handy way with gulp-environments : 您也可以使用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:

gulp build --env=production

Unfortunately none of the above answers work, because setting process.env.NODE_ENV has no effect in Browserify. 遗憾的是,上述答案都不起作用,因为设置process.env.NODE_ENV在Browserify中没有效果。 The resulting bundle still has process.env.NODE_ENV references in it and hence 生成的bundle仍然包含process.env.NODE_ENV引用,因此

  • Browserify will not require() the React production version modules, Browserify require() React生产版本模块,
  • the minifier will not be able to remove dead code, and minifier将无法删除死代码,并且
  • 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 eg 正确的方法可以在例如

You need to switch the envify transform to be a global one, eg 您需要将envify转换切换为全局转换,例如

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

or in gulpfile.js 或者在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
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM