【问题标题】:How to set React to production mode when using Gulp使用 Gulp 时如何将 React 设置为生产模式
【发布时间】:2015-12-08 04:20:41
【问题描述】:

我需要在生产模式下运行 React,这大概需要在环境中的某处定义以下内容:

process.env.NODE_ENV = 'production';

问题是我在 Tornado(python 网络服务器)而不是 Node.js 后面运行它。我也使用 Supervisord 来管理 tornado 实例,所以不清楚如何在运行环境中设置它。

不过,我确实使用 Gulp 将我的 jsx 文件构建为 javascript。

是否有可能以某种方式在 Gulp 中设置它?如果是这样,我如何检查 React 是否在生产模式下运行?

这是我的 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() {});

【问题讨论】:

  • 从我可以从有关生产与开发的反应文档中收集到的信息,意味着使用不同的工件。见下载页面:facebook.github.io/react/downloads.html
  • React 是通过 npm 安装的,即“npm install react”。在开发和生产之间有一种无缝切换的方式,这就是我在问题中所要求的
  • 您可以在生产环境中运行 gulp 之前设置环境变量:NODE_ENV='production' gulp. react 库将从这里读取以删除日志消息和警报,而 uglifyJS 将处理其余的 http://facebook.github.io/react/downloads.html。

标签: javascript python flask reactjs tornado


【解决方案1】:

2017 - 编辑:任何试图在 Gulp 中为新项目设置 React 的人:只需使用 create-react-app


第一步:将以下内容添加到您的 gulpfile.js 中

gulp.task('apply-prod-environment', function() {
    process.env.NODE_ENV = 'production';
});

第二步:将其添加到您的默认任务(或您用于服务/构建应用程序的任何任务)

// before: 
// gulp.task('default',['browsersync','watch'], function() {});
// after:
   gulp.task('default',['apply-prod-environment', 'browsersync','watch'], function() {});

可选:如果您想完全确定自己处于 prod 模式,您可以创建以下稍微增强的任务,而不是步骤 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");
    }
});

如果 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!!!!

【讨论】:

  • 什么情况下会抛出错误?是否存在无法写入个人环境变量的情况?
  • 据我所知没有这种情况。可选步骤实际上可能是不必要的。
  • 如果我错了,请纠正我,但 gulp 中的任务顺序在技术上并不能保证。那么在应用 prod 环境之前,watch 和 browsersync 可能不会发生吗?
  • 我预计尺寸会发生明显变化,但似乎差异大约是 2ko 差异(未压缩),有人可以确认吗?
【解决方案2】:

与其他答案类似,但希望能给某人一个起点:

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'));
});

主要区别在于我在捆绑供应商库之前明确设置了 NODE_ENV。 Gulp 任务不能保证按顺序运行。

我是否在生产模式下运行?

如果您删除 uglify 行(和之前的缓冲区),您会注意到开发版本和生产版本的大小几乎相同 - 并且行数匹配。

不同的是生产版本会乱七八糟:

"production" !== "production" ? [show dev error] : [no nothing]

大多数有信誉的 minify'ers(我相信)会去除死端代码,例如上面的,这将始终导致错误。

但我真的该怎么说呢?

确定最简单的方法是转到正在运行的应用程序的控制台并输入:

React.createClass.toString();

输出应该是:

"function (e){var t=function(e,t,n){this.__reactAutoBindMap&&c(this),"[....and more and more]

如果你在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);
      }

请注意控制台输出如何直接跳到this.__reactAutobind,因为您在生产模式下运行,并且使用了缩小器,所有 !== 'production' 警告和检查都已被跳过。

【讨论】:

  • 太棒了。在任务本身中显式设置 NODE_ENV 是它对我有用的唯一方法。
  • 不用担心。是的,这对我来说是一样的
【解决方案3】:

不幸的是,以上答案都不起作用,因为设置 process.env.NODE_ENV 在 Browserify 中无效。生成的包中仍然有 process.env.NODE_ENV 引用,因此

  • Browserify 不会require() React 生产版本模块,
  • 缩小器将无法删除死代码,并且
  • 应用程序仍将在调试模式下运行。

不幸的是,这不是提供这种方法作为正确答案的唯一地方:-(


正确的方法可以在例如中找到

您需要将 envify 转换切换为全局转换,例如

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

或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
    ...

【讨论】:

    【解决方案4】:

    要将 React 设置为生产模式,您需要将 NODE_ENV 变量设置为生产,并将 JS 丑化作为额外的步骤。

    你已经在处理丑化,设置你的 NODE_ENV 变量:

    • 在运行 gulp 任务时设置变量:

    NODE_ENV='production' gulp

    • 或通过执行以下操作从您的 gulpfile 中设置它:

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

    【讨论】:

    • 如何检查 React 是否在生产模式下工作?有没有办法在开发控制台中检查模式?
    • 一种方法是触发一些会导致警告的东西并检查控制台中是否存在警告日志。例如,将一个数组映射到一堆组件并且不给它们一个键。如果没有向控制台写入任何内容,则说明您处于生产模式。此外,请确保 react lib 已正确缩小、丑化和 gzip 压缩以适应文件大小。
    • 感谢您的帮助:)
    • 另一种方法是检查最终缩小的应用程序/浏览器包的大小。我刚刚看到我的包大小在生产集下减少了大约 100kB。
    【解决方案5】:

    您也可以使用方便的方式与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/"));
    

    在生产模式下运行 gulp:

    gulp build --env=production
    

    【讨论】:

      猜你喜欢
      • 2018-06-03
      • 1970-01-01
      • 2019-01-09
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 2021-12-13
      • 2018-08-20
      相关资源
      最近更新 更多