Los scripts de NPM pueden hacer lo mismo que gulp, pero en aproximadamente 50 veces menos código. De hecho, sin ningún código, solo argumentos de línea de comando.
Por ejemplo, el caso de uso que describió donde desea tener un código diferente para diferentes entornos.
Con Webpack + NPM Scripts, es así de fácil:
"prebuild:dev": "npm run clean:wwwroot",
"build:dev": "cross-env NODE_ENV=development webpack --config config/webpack.development.js --hot --profile --progress --colors --display-cached",
"postbuild:dev": "npm run copy:index.html && npm run rename:index.html",
"prebuild:production": "npm run clean:wwwroot",
"build:production": "cross-env NODE_ENV=production webpack --config config/webpack.production.js --profile --progress --colors --display-cached --bail",
"postbuild:production": "npm run copy:index.html && npm run rename:index.html",
"clean:wwwroot": "rimraf -- wwwroot/*",
"copy:index.html": "ncp wwwroot/index.html Views/Shared",
"rename:index.html": "cd ../PowerShell && elevate.exe -c renamer --find \"index.html\" --replace \"_Layout.cshtml\" \"../MyProject/Views/Shared/*\"",
Ahora simplemente mantiene dos scripts de configuración de paquete web, uno para el modo de desarrollo webpack.development.js
y otro para el modo de producción webpack.production.js
. También utilizo una webpack.common.js
que contiene la configuración de webpack compartida en todos los entornos, y uso webpackMerge para fusionarlos.
Debido a la frescura de los scripts de NPM, permite un encadenamiento fácil, similar a la forma en que Gulp hace Streams / pipes.
En el ejemplo anterior, para construir para el desarrollo, simplemente vaya a su línea de comando y ejecute npm run build:dev
.
- NPM correría primero
prebuild:dev
,
- entonces
build:dev
,
- Y, por último
postbuild:dev
.
Los prefijos pre
y le post
dicen a NPM en qué orden ejecutar.
Si observa, con los scripts Webpack + NPM, puede ejecutar programas nativos, como rimraf
, en lugar de un gulp-wrapper para un programa nativo como gulp-rimraf
. También puede ejecutar archivos .exe nativos de Windows como lo hice aquí con elevate.exe
archivos nativos * nix en Linux o Mac.
Intenta hacer lo mismo con trago. Tendrá que esperar a que alguien venga y escriba una envoltura para el programa nativo que desea usar. Además, es probable que deba escribir un código complicado como este: (tomado directamente del repositorio angular2-seed )
Código de desarrollo de Gulp
import * as gulp from 'gulp';
import * as gulpLoadPlugins from 'gulp-load-plugins';
import * as merge from 'merge-stream';
import * as util from 'gulp-util';
import { join/*, sep, relative*/ } from 'path';
import { APP_DEST, APP_SRC, /*PROJECT_ROOT, */TOOLS_DIR, TYPED_COMPILE_INTERVAL } from '../../config';
import { makeTsProject, templateLocals } from '../../utils';
const plugins = <any>gulpLoadPlugins();
let typedBuildCounter = TYPED_COMPILE_INTERVAL; // Always start with the typed build.
/**
* Executes the build process, transpiling the TypeScript files (except the spec and e2e-spec files) for the development
* environment.
*/
export = () => {
let tsProject: any;
let typings = gulp.src([
'typings/index.d.ts',
TOOLS_DIR + '/manual_typings/**/*.d.ts'
]);
let src = [
join(APP_SRC, '**/*.ts'),
'!' + join(APP_SRC, '**/*.spec.ts'),
'!' + join(APP_SRC, '**/*.e2e-spec.ts')
];
let projectFiles = gulp.src(src);
let result: any;
let isFullCompile = true;
// Only do a typed build every X builds, otherwise do a typeless build to speed things up
if (typedBuildCounter < TYPED_COMPILE_INTERVAL) {
isFullCompile = false;
tsProject = makeTsProject({isolatedModules: true});
projectFiles = projectFiles.pipe(plugins.cached());
util.log('Performing typeless TypeScript compile.');
} else {
tsProject = makeTsProject();
projectFiles = merge(typings, projectFiles);
}
result = projectFiles
.pipe(plugins.plumber())
.pipe(plugins.sourcemaps.init())
.pipe(plugins.typescript(tsProject))
.on('error', () => {
typedBuildCounter = TYPED_COMPILE_INTERVAL;
});
if (isFullCompile) {
typedBuildCounter = 0;
} else {
typedBuildCounter++;
}
return result.js
.pipe(plugins.sourcemaps.write())
// Use for debugging with Webstorm/IntelliJ
// https://github.com/mgechev/angular2-seed/issues/1220
// .pipe(plugins.sourcemaps.write('.', {
// includeContent: false,
// sourceRoot: (file: any) =>
// relative(file.path, PROJECT_ROOT + '/' + APP_SRC).replace(sep, '/') + '/' + APP_SRC
// }))
.pipe(plugins.template(templateLocals()))
.pipe(gulp.dest(APP_DEST));
};
Código de producción de Gulp
import * as gulp from 'gulp';
import * as gulpLoadPlugins from 'gulp-load-plugins';
import { join } from 'path';
import { TMP_DIR, TOOLS_DIR } from '../../config';
import { makeTsProject, templateLocals } from '../../utils';
const plugins = <any>gulpLoadPlugins();
const INLINE_OPTIONS = {
base: TMP_DIR,
useRelativePaths: true,
removeLineBreaks: true
};
/**
* Executes the build process, transpiling the TypeScript files for the production environment.
*/
export = () => {
let tsProject = makeTsProject();
let src = [
'typings/index.d.ts',
TOOLS_DIR + '/manual_typings/**/*.d.ts',
join(TMP_DIR, '**/*.ts')
];
let result = gulp.src(src)
.pipe(plugins.plumber())
.pipe(plugins.inlineNg2Template(INLINE_OPTIONS))
.pipe(plugins.typescript(tsProject))
.once('error', function () {
this.once('finish', () => process.exit(1));
});
return result.js
.pipe(plugins.template(templateLocals()))
.pipe(gulp.dest(TMP_DIR));
};
El código de gulp real es mucho más complicado que esto, ya que esto es solo 2 de las varias docenas de archivos de gulp en el repositorio.
Entonces, ¿cuál es más fácil para ti?
En mi opinión, los scripts de NPM superan con creces el trago y el gruñido, tanto en efectividad como en facilidad de uso, y todos los desarrolladores front-end deberían considerar usarlo en su flujo de trabajo porque es un gran ahorro de tiempo.
ACTUALIZAR
Hay un escenario que he encontrado en el que quería usar Gulp en combinación con scripts NPM y Webpack.
Cuando necesito hacer una depuración remota en un dispositivo iPad o Android, por ejemplo, necesito iniciar servidores adicionales. En el pasado, ejecuté todos los servidores como procesos separados, desde IntelliJ IDEA (o Webstorm) que es fácil con la Configuración de ejecución "Compuesta". Pero si necesito detenerlos y reiniciarlos, fue tedioso tener que cerrar 5 pestañas de servidor diferentes, además la salida se extendió por las diferentes ventanas.
Uno de los beneficios de Gulp es que puede encadenar toda la salida de procesos independientes separados en una ventana de consola, que se convierte en el padre de todos los servidores secundarios.
Así que creé una tarea gulp muy simple que solo ejecuta mis scripts NPM o los comandos directamente, de modo que toda la salida aparece en una ventana, y puedo finalizar fácilmente los 5 servidores a la vez cerrando la ventana de la tarea gulp.
Gulp.js
/**
* Gulp / Node utilities
*/
var gulp = require('gulp-help')(require('gulp'));
var utils = require('gulp-util');
var log = utils.log;
var con = utils.colors;
/**
* Basic workflow plugins
*/
var shell = require('gulp-shell'); // run command line from shell
var browserSync = require('browser-sync');
/**
* Performance testing plugins
*/
var ngrok = require('ngrok');
// Variables
var serverToProxy1 = "localhost:5000";
var finalPort1 = 8000;
// When the user enters "gulp" on the command line, the default task will automatically be called. This default task below, will run all other tasks automatically.
// Default task
gulp.task('default', function (cb) {
console.log('Starting dev servers!...');
gulp.start(
'devserver:jit',
'nodemon',
'browsersync',
'ios_webkit_debug_proxy'
'ngrok-url',
// 'vorlon',
// 'remotedebug_ios_webkit_adapter'
);
});
gulp.task('nodemon', shell.task('cd ../backend-nodejs && npm run nodemon'));
gulp.task('devserver:jit', shell.task('npm run devserver:jit'));
gulp.task('ios_webkit_debug_proxy', shell.task('npm run ios-webkit-debug-proxy'));
gulp.task('browsersync', shell.task(`browser-sync start --proxy ${serverToProxy1} --port ${finalPort1} --no-open`));
gulp.task('ngrok-url', function (cb) {
return ngrok.connect(finalPort1, function (err, url) {
site = url;
log(con.cyan('ngrok'), '- serving your site from', con.yellow(site));
cb();
});
});
// gulp.task('vorlon', shell.task('vorlon'));
// gulp.task('remotedebug_ios_webkit_adapter', shell.task('remotedebug_ios_webkit_adapter'));
Todavía un poco de código solo para ejecutar 5 tareas, en mi opinión, pero funciona para ese propósito. Una advertencia es que gulp-shell
no parece ejecutar algunos comandos correctamente, como ios-webkit-debug-proxy
. Así que tuve que crear un script NPM que solo ejecuta el mismo comando, y luego funciona.
Así que principalmente uso NPM Scripts para todas mis tareas, pero ocasionalmente cuando necesito ejecutar un montón de servidores a la vez, enciendo mi tarea Gulp para ayudar. Elija la herramienta adecuada para el trabajo correcto.
ACTUALIZACIÓN 2
Ahora uso un script llamado concurrentemente que hace lo mismo que la tarea anterior. Ejecuta múltiples scripts de CLI en paralelo y los canaliza a todos a la misma ventana de la consola, y es muy fácil de usar. Una vez más, no se requiere código (bueno, el código está dentro del nodo_módulo al mismo tiempo, pero no tiene que preocuparse por eso)
// NOTE: If you need to run a command with spaces in it, you need to use
// double quotes, and they must be escaped (at least on windows).
// It doesn't seem to work with single quotes.
"run:all": "concurrently \"npm run devserver\" nodemon browsersync ios_webkit_debug_proxy ngrok-url"
Esto ejecuta los 5 scripts en paralelo canalizados a un terminal. ¡Increíble! Para este punto, rara vez uso trago, ya que hay tantos cli scripts para hacer las mismas tareas sin código.
Le sugiero que lea estos artículos que los comparan en profundidad.