Как установить режим "Реагировать в производство" при использовании Gulp

Мне нужно запустить React в режиме производства, который предположительно предполагает определение следующего в enviornment:

process.env.NODE_ENV = 'production';

Проблема в том, что я запускаю это за Tornado (веб-сервер python), а не Node.js. Я также использую Supervisord для управления экземплярами торнадо, поэтому он совершенно не ясно, как установить это в рабочей среде.

Однако я использую 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() {});

Ответ 1

2017 - Изменить: любой, кто пытается настроить React в Gulp для нового проекта: Просто используйте create-react-app


Шаг I: Добавьте в свой gulpfile.js следующее:

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

Шаг II: Добавьте его в задание по умолчанию (или какую бы задачу вы не использовали для создания/создания вашего приложения)

// 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 никогда не установлен в '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!!!!

Ответ 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 (и предыдущий буфер), вы заметите, что обе сборки dev и production почти идентичны по размеру и соответствуют количеству строк.

Разница заключается в том, что производственная версия будет засорена:

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

Самые уважаемые мини-разработчики (я считаю) вычеркнут мертвый код, например, выше, который всегда будет приводить к ложному.

Но действительно, как я могу сказать?

Самый простой способ быть уверенным, что бы получить консоль вашего запущенного приложения и введите:

React.createClass.toString();

Выход должен быть:

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

Если вы обнаружите 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, потому что вы работаете в режиме производства и с помощью minify'er все предупреждения и проверки 'production' были пропущены.

Ответ 3

Чтобы установить режим "Реакт в рабочем режиме", вам нужно настроить свою переменную NODE_ENV на производство и активировать JS как дополнительный шаг.

Вы уже заботитесь об угасании, для установки своей переменной NODE_ENV:

  • Задайте переменную во время выполнения задачи gulp:

NODE_ENV='production' gulp

  • ИЛИ установите его внутри вашего gulpfile, выполнив что-то вроде этого:

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

Ответ 4

Также вы можете использовать удобный способ с 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

Ответ 5

К сожалению, ни один из вышеперечисленных ответов не работает, потому что установка process.env.NODE_ENV не влияет на Browserify. Полученный в результате пакет все еще имеет process.env.NODE_ENV ссылки в нем и, следовательно,

  • Browserify не будет require() версиями модулей версии React,
  • minifier не сможет удалить мертвый код и
  • приложение все еще будет работать в режиме отладки.

Это, к сожалению, не единственное место, где этот подход предлагается в качестве правильного ответа: - (


Правильный подход можно найти, например,

Вам нужно переключить преобразование 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
    ...