Gulp + Webpack o JUST Webpack?

161

Veo personas que usan trago con webpack. Pero luego leí webpack puede reemplazar gulp? Estoy completamente confundido aquí ... ¿alguien puede explicar?

ACTUALIZAR

Al final empecé con trago. Era nuevo en el front-end moderno y solo quería ponerme en marcha rápidamente. Ahora que tengo los pies bastante mojados después de más de un año, estoy listo para pasar a la webpack. Sugiero la misma ruta para las personas que comienzan con los mismos zapatos. No digo que no puedas probar el paquete web, solo di que si parece complicado, comienza con un trago primero ... nada de malo en eso.

Si no quiere tragar, sí, hay gruñidos, pero también puede especificar comandos en su package.json y llamarlos desde la línea de comandos sin un corredor de tareas solo para comenzar a funcionar inicialmente. Por ejemplo:

"scripts": {
      "babel": "babel src -d build",
      "browserify": "browserify build/client/app.js -o dist/client/scripts/app.bundle.js",
      "build": "npm run clean && npm run babel && npm run prepare && npm run browserify",
      "clean": "rm -rf build && rm -rf dist",
      "copy:server": "cp build/server.js dist/server.js",
      "copy:index": "cp src/client/index.html dist/client/index.html",
      "copy": "npm run copy:server && npm run copy:index",
      "prepare": "mkdir -p dist/client/scripts/ && npm run copy",
      "start": "node dist/server"
    },
PositivoGuy
fuente
3
Esto me ha ayudado a comprender Webpack mejor que los propios documentos de Webpack o cualquier artículo: github.com/petehunt/webpack-howto
George Ananda Eman
blog.andrewray.me/webpack-when-to-use-and-why no es necesario usar trago con webpack
Andy Ray
Mi ejemplo simple y sencillo sería que quiero que webpack-dev-server maneje mi js con HMR, pero estoy experimentando problemas en los que no puedo usar generadores de sitios estáticos y webpack dev server. Con una configuración complicada puedo lograr esto, pero es un trago directo que también puedo hacerlo. Entonces, la principal diferencia es el tiempo y la curva de aprendizaje.
dewwwald
2 años después, todavía lucho por problemas similares ...
Frank Nocke
su actualización debería ser una respuesta, +1
Z. Khullah

Respuestas:

82

Esta respuesta podría ayudar. Task Runners (Gulp, Grunt, etc.) y Bundlers (Webpack, Browserify). ¿Por qué usar juntos?

... y aquí hay un ejemplo del uso de webpack desde una tarea de trago. Esto va un paso más allá y supone que la configuración de su paquete web está escrita en es6.

var gulp = require('gulp');
var webpack = require('webpack');
var gutil = require('gutil');
var babel = require('babel/register');
var config = require(path.join('../..', 'webpack.config.es6.js'));

gulp.task('webpack-es6-test', function(done){
   webpack(config).run(onBuild(done));
});

function onBuild(done) {
    return function(err, stats) {
        if (err) {
            gutil.log('Error', err);
            if (done) {
                done();
            }
        } else {
            Object.keys(stats.compilation.assets).forEach(function(key) {
                gutil.log('Webpack: output ', gutil.colors.green(key));
            });
            gutil.log('Webpack: ', gutil.colors.blue('finished ', stats.compilation.name));
            if (done) {
                done();
            }
        }
    }
}

Creo que encontrará que a medida que su aplicación se vuelve más complicada, es posible que desee usar trago con una tarea de paquete web como se muestra en el ejemplo anterior. Esto le permite hacer algunas cosas más interesantes en su compilación que los cargadores de paquetes web y los complementos realmente no hacen, es decir. crear directorios de salida, iniciar servidores, etc. Bueno, para ser sucinto, el paquete web en realidad puede hacer esas cosas, pero puede encontrarlas limitadas para sus necesidades a largo plazo. Una de las mayores ventajas que obtienes de gulp -> webpack es que puedes personalizar tu configuración de webpack para diferentes entornos y hacer que gulp haga la tarea correcta en el momento adecuado. Realmente depende de usted, pero no hay nada de malo en ejecutar webpack desde Gulp, de hecho, hay algunos ejemplos bastante interesantes de cómo hacerlo..

4m1r
fuente
Mi proyecto webpack es bastante grande, así que necesito aumentar la memoria del nodo también a través del comando de línea de comando stackoverflow.com/questions/34727743/… ¿Hay alguna forma de hacerlo directamente a través de webpack?
Abhinav Singi
Mira estos dos. Es probable que tenga que configurar la memoria v8 antes de ejecutar el nodo o el paquete web. stackoverflow.com/questions/7193959/… y webpack.github.io/docs/build-performance.html
4m1r
No estoy seguro de por qué acepté esto como respuesta. Supongo que probablemente se deba al primer enlace que compartiste. ¿Pero usando webpack de trago? eso es aún más complicado si me preguntas ahora :). Ni siquiera trataría de recurrir a algo así.
PositiveGuy
80

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.jsy otro para el modo de producción webpack.production.js. También utilizo una webpack.common.jsque 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.

  1. NPM correría primero prebuild:dev,
  2. entonces build:dev,
  3. Y, por último postbuild:dev.

Los prefijos prey le postdicen 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.exearchivos 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-shellno 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.

TetraDev
fuente
14
Eso es porque tus tareas son relativamente fáciles. Buena suerte compilaciones complejas con shell :-)
Filip Sobczak
55
Estos son solo ejemplos. Mi compilación es muy compleja y tiene muchos scripts ejecutándose en shell, funciona perfectamente y es fácil de mantener. Y, lo que los scripts de NPM no hacen por mí, webpack lo hace, como uglify, comprimir gzip, transformar, etc. Gracias. ¿Qué es tan complejo para lo que necesitas tragar?
TetraDev
2
(más de un año después jajaja): muchas gracias, excelente respuesta !!
PositiveGuy
1
@ user108471 Sure webpack puede, puede crear assets.json que enumera todos los módulos compilados con sus ID asociados. Se pueden crear muchos más tipos de archivos JSON de información de tiempo de compilación con los complementos correctos. ¿A qué tipo se refiere específicamente que puede hacer ese trago?
TetraDev
1
@GiannosCharalambous Gracias por ese consejo. De hecho, he estado usando npm-run-alldurante algunos meses, ¡pero ni siquiera pensé en usar la -pbandera paralela!
Probaré
8

Usé ambas opciones en mis diferentes proyectos.

Aquí hay una repetitiva que puse junto gulpcon webpack- https://github.com/iroy2000/react-reflux-boilerplate-with-webpack .

Tengo otro proyecto utilizado solo webpackcon npm tasks.

Y ambos funcionan totalmente bien. Y creo que se reduce a cuán complicada es su tarea y cuánto control desea tener en su configuración.

Por ejemplo, si usted tareas es simple, digamos dev, build, test... etc (que es muy estándar), que está totalmente bien con sólo simple webpackcon npm tasks.

Pero si tiene un flujo de trabajo muy complicado y desea tener un mayor control de su configuración (porque está codificando), puede optar por la ruta de trago.

Pero desde mi experiencia, el ecosistema webpack proporciona complementos y cargadores más que suficientes que necesitaré, por lo que me encanta usar el enfoque mínimo básico a menos que haya algo que solo pueda hacer en trago. Y también, facilitará su configuración si tiene una cosa menos en su sistema.

Y muchas veces, hoy en día, veo personas que realmente reemplazan a gulp and browsifytodas juntas webpack.

RR
fuente
55
Sí, pero Webpack ha tenido una mala reputación de ser demasiado complicado de entender. Tiendo a tratar de usar gulp primero con browserify, todavía no estoy listo para enfrentarme a Webpack y en parte es que no he hecho mucho con Browserify o el nodo en el front-end, así que quiero aprender cómo todos lo están haciendo con gulp y browserify primero para tener esa historia en términos de experiencia
PositiveGuy
1
Webpack solo es complicado si no ha trabajado con él, como gulp, gruñido, browserify, mecanografiado y cualquier otra cosa. Webpack es extremadamente fácil de usar una vez que comprende cómo configurar el archivo de configuración y trabajar con los cargadores. De hecho, los archivos de configuración pueden ser tan cortos como 20-30 líneas de código para una compilación de paquete web en funcionamiento, y pueden ser tan robustos como sea necesario. Sin mencionar que Webpack Hot Module Replacement es absolutamente sorprendente. Ver: andrewhfarmer.com/understanding-hmr y andrewhfarmer.com/webpack-hmr-tutorial and medium.com/@dabit3/beginner-s-guide-to-webpack-b1f1a3638460
TetraDev
2

Los conceptos de Gulp y Webpack son bastante diferentes. Le dice a Gulp cómo armar el código de front-end, paso a paso, pero le dice a Webpack lo que quiere a través de un archivo de configuración.

Aquí hay un breve artículo (5 minutos de lectura) que escribí explicando mi comprensión de las diferencias: https://medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack-c45671ad87fe

Nuestra empresa se mudó de Gulp a Webpack el año pasado. Aunque tomó algo de tiempo, descubrimos cómo mover todo lo que hicimos en Gulp a Webpack. Entonces, para nosotros, todo lo que hicimos en Gulp también lo podemos hacer a través de Webpack, pero no al revés.

A partir de hoy, sugiero usar Webpack y evitar la combinación de Gulp y Webpack para que usted y su equipo no necesiten aprender y mantener ambos, especialmente porque requieren mentalidades muy diferentes.

Maokai
fuente
2

Sinceramente, creo que lo mejor es usar ambos.

  • Webpack para todos los javascript relacionados.
  • Gulp para todos los css relacionados.

Todavía tengo que encontrar una solución decente para empaquetar css con webpack, y hasta ahora estoy feliz de usar gulp para css y webpack para javascript.

También uso npmscripts como @Tetradev como se describe. Expecially Desde que estoy usando Visual Studio, y si bien NPM Task runneres bastante fiable Webpack Task Runner es bastante cochecito .

Max Favilli
fuente
He encontrado usando el NPM Task Runner + Gulp la clave. Coloque los comandos del paquete web en el archivo packange.json y el CSS (SASS) relacionado en el archivo gulp. También configure el package.json para que tenga un paso de compilación que llame a una tarea de trago como parte del lanzamiento de producción
Nico