javascript - commands - Cómo establecer el modo Reaccionar en producción cuando se usa Gulp
npm gulp (5)
Necesito ejecutar React en modo de producción, lo que presumiblemente implica definir lo siguiente en algún lugar del entorno:
process.env.NODE_ENV = ''production'';
El problema es que estoy ejecutando esto detrás de Tornado (un servidor web de python), no de Node.js. También uso Supervisord para administrar las instancias de tornado, por lo que no está muy claro cómo configurar esto en el entorno de ejecución.
Sin embargo, utilizo Gulp para compilar mis archivos jsx en javascript.
¿Es posible de alguna manera establecer esto dentro de Gulp? Y si es así, ¿cómo puedo verificar que React se esté ejecutando en modo de producción?
Aquí está mi 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 - Edición: cualquiera que intente configurar React in Gulp para un nuevo proyecto: simplemente use create-react-app
Paso I: Agregue lo siguiente a su gulpfile.js en algún lado
gulp.task(''apply-prod-environment'', function() {
process.env.NODE_ENV = ''production'';
});
Paso II: agréguelo a su tarea predeterminada (o a cualquier tarea que use para servir / crear su aplicación)
// before:
// gulp.task(''default'',[''browsersync'',''watch''], function() {});
// after:
gulp.task(''default'',[''apply-prod-environment'', ''browsersync'',''watch''], function() {});
OPCIONAL: si quiere estar ABSOLUTAMENTE SEGURO de que se encuentra en el modo prod, puede crear la siguiente tarea ligeramente mejorada en lugar de la del Paso 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");
}
});
Que arrojará el siguiente error si NODE_ENV alguna vez está configurado como ''producción''
[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!!!!
Lamentablemente, ninguna de las respuestas anteriores funciona, porque la configuración de process.env.NODE_ENV
no tiene ningún efecto en Browserify. El paquete resultante todavía tiene referencias process.env.NODE_ENV
en él y, por lo tanto,
- Browserify no
require()
los módulos de versión de producción Reaccionar, - el minificador no podrá eliminar el código muerto, y
- la aplicación seguirá ejecutándose en modo de depuración.
Desafortunadamente, este no es el único lugar donde se ofrece este enfoque como la respuesta correcta :-(
El enfoque correcto se puede encontrar, por ejemplo, en
- https://github.com/hughsk/envify/issues/15#issuecomment-62229101
- https://reactjs.org/docs/optimizing-performance.html#browserify
Necesita cambiar la transformación envify para que sea global, por ejemplo
# note the "-g" instead of the usual "-t"
$ browserify ... -g [ envify --NODE_ENV production ] ....
o en 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
...
Para configurar Reaccionar en modo de producción, necesita establecer su variable NODE_ENV a producción y uglificar su JS como un paso adicional.
Ya se está ocupando de la uglificación, para configurar su variable NODE_ENV:
- Establezca la variable mientras ejecuta la tarea de trago:
NODE_ENV=''production'' gulp
- O configúralo desde dentro de tu gulpfile haciendo algo como esto:
gulp.task(''set-production-env'', function() { return process.env.NODE_ENV = ''production''; });
Similar a las otras respuestas, pero con suerte le da a alguien un punto de partida:
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''));
});
La principal diferencia es que estoy configurando explícitamente el NODE_ENV antes de agrupar las bibliotecas del proveedor. Las tareas de Gulp no están garantizadas para ejecutarse en orden.
¿Me estoy ejecutando en modo de producción?
Si elimina la línea uglify (y el búfer anterior), notará que las compilaciones dev y production son casi idénticas en tamaño y coinciden en el recuento de líneas.
La diferencia es que la versión de producción estará plagada de:
"production" !== "production" ? [show dev error] : [no nothing]
La mayoría de los minify''ers de buena reputación (creo) eliminarán el código de desactivación, como el anterior, que siempre dará como resultado el falso.
Pero realmente, ¿cómo lo digo?
El método más sencillo para estar seguro sería ir a la consola de la aplicación en ejecución y escribir:
React.createClass.toString();
El resultado debería ser:
"function (e){var t=function(e,t,n){this.__reactAutoBindMap&&c(this),"[....and more and more]
Si encuentra el createClass en la fuente de reacción, verá:
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);
}
Observe cómo la salida de la consola salta directamente a this.__reactAutobind
, porque se está ejecutando en modo de producción, y utilizando un minify''er, todos los warngins y controles de ''!'' ''Producción'' se saltearon.
También puede usar la forma práctica con 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/"));
Para ejecutar gulp en modo de producción:
gulp build --env=production