webentwicklung-frage-antwort-db.com.de

Wie kann man bei Verwendung von Gulp auf den Produktionsmodus reagieren?

Ich muss React im Produktionsmodus ausführen, was vermutlich dazu führt, dass irgendwo in der Umgebung Folgendes definiert wird:

process.env.NODE_ENV = 'production';

Das Problem ist, dass ich dies hinter Tornado (einem Python-Webserver) und nicht hinter Node.js führe. Ich verwende auch Supervisord, um die Tornado-Instanzen zu verwalten. Daher ist nicht klar, wie dies in der laufenden Umgebung eingestellt werden muss.

Ich benutze jedoch Gulp, um meine jsx-Dateien in Javascript zu erstellen. 

Kann man das irgendwie in Gulp einstellen? Und wenn ja, wie kann ich überprüfen, ob React im Produktionsmodus läuft?

Hier ist meine 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() {});
28
vgoklani

2017 - Bearbeiten: Jeder, der versucht, React in Gulp für ein neues Projekt einzurichten: Benutze einfach create -rease-app


Schritt I: Fügen Sie Ihrer Datei gulpfile.js irgendwo Folgendes hinzu

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

Schritt II: Fügen Sie es Ihrer Standardaufgabe hinzu (oder der Aufgabe, die Sie zum Bereitstellen/Erstellen Ihrer App verwenden).

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

OPTIONAL: Wenn Sie sich absolut sicher sein wollen, dass Sie sich im Prod-Modus befinden, können Sie die folgende, etwas erweiterte Aufgabe anstelle der Aufgabe in Schritt I erstellen:

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

Welcher wird den folgenden Fehler auslösen, wenn NODE_ENV jemals nicht auf 'production' gesetzt ist

[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!!!!
29
Monarch Wadia

Ähnlich wie die anderen Antworten, aber hoffentlich gibt jemandem einen Ausgangspunkt:

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

Der Hauptunterschied besteht darin, dass ich den NODE_ENV vor dem Bündeln der Herstellerbibliotheken explizit setze. Gulp-Aufgaben laufen nicht garantiert in Ordnung. 

Läuft ich im Produktionsmodus?

Wenn Sie die uglify-Zeile (und den vorherigen Puffer) entfernen, werden Sie feststellen, dass sowohl die Entwicklungs- als auch die Produktions-Builds in der Größe nahezu identisch sind und in der Zeilenanzahl übereinstimmen.

Der Unterschied ist, dass die Produktionsversion mit verunreinigt wird:

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

Die meisten seriösen Minifyer (ich glaube) werden Dead-Code wie den oben genannten entfernen, was immer zu einem falschen Ergebnis führt. 

Aber wie erzähle ich es wirklich?

Die einfachste Methode, um sicherzugehen, wäre die Konsole Ihrer laufenden Anwendung und geben Sie ein:

React.createClass.toString();

Die Ausgabe sollte sein:

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

Wenn Sie die createClass in der React-Quelle finden, sehen Sie Folgendes:

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

Beachten Sie, wie die Konsolenausgabe direkt zu this.__reactAutobind springt, da Sie im Produktionsmodus ausgeführt werden und mit einem Minify'er alle! == 'Production'-Warngins und -Kontrollen übersprungen wurden. 

7
Chris

Um React im Produktionsmodus zu setzen, müssen Sie Ihre NODE_ENV-Variable auf Production setzen und Ihren JS als zusätzlichen Schritt festlegen. 

Sie kümmern sich bereits um die Uglification, um Ihre NODE_ENV-Variable festzulegen: 

  • Legen Sie die Variable fest, während Sie die Schluckaufgabe ausführen: 

NODE_ENV='production' gulp

  • ODER setzen Sie es aus Ihrem gulpfile, indem Sie Folgendes tun: 

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

1
Rakan Nimer

Leider funktioniert keine der obigen Antworten, da die Einstellung von process.env.NODE_ENV in Browserify keine Auswirkung hat. Das resultierende Bundle enthält noch process.env.NODE_ENV-Verweise und somit

  • Browserify require() die Module der React-Produktionsversion nicht
  • der Minifier kann keinen toten Code entfernen, und
  • die Anwendung wird weiterhin im Debug-Modus ausgeführt.

Dies ist leider nicht der einzige Ort, an dem dieser Ansatz als richtige Antwort angeboten wird :-(


Der richtige Ansatz kann z.

Sie müssen die envify-Transformation in eine globale umwandeln, z.

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

oder 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
Stefan Becker

Sie können auch eine praktische Methode mit gulp-environments verwenden:

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/"));

Schluck im Produktionsmodus ausführen:

gulp build --env=production
0
mnv