Gulp + Webpack ou APENAS Webpack?

161

Eu vejo pessoas usando gulp com webpack. Mas então eu li webpack pode substituir gulp? Estou completamente confuso aqui ... alguém pode explicar?

ATUALIZAR

no final, comecei com gole. Eu era novo no front-end moderno e só queria começar a trabalhar rapidamente. Agora que estou com os pés bastante molhados depois de mais de um ano, estou pronto para mudar para o webpack. Sugiro o mesmo caminho para pessoas que começam com os mesmos sapatos. Não estou dizendo que você não pode tentar o webpack, mas apenas dizendo se parece complicado começar com o gole primeiro ... nada de errado nisso.

Se você não quer gulp, sim, há um grunhido, mas você também pode especificar comandos no seu package.json e chamá-los na linha de comando sem um executor de tarefas, apenas para começar a funcionar inicialmente. Por exemplo:

"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"
    },
PositiveGuy
fonte
3
Isso me ajudou a compreender Webpack melhor do que próprios documentos de Webpack ou qualquer artigo: github.com/petehunt/webpack-howto
George Ananda Eman
blog.andrewray.me/webpack-when-to-use-and-why há necessidade de uso gole com Webpack
Andy Ray
Meu exemplo claro e simples seria que eu quero que o webpack-dev-server manipule meus js com o HMR, mas estou tendo problemas em que não posso usar geradores de sites estáticos e servidor de desenvolvimento webpack. Com uma configuração complicada eu posso conseguir isso, mas é um gole direto que posso fazer também. Portanto, a principal diferença é o tempo e a curva de aprendizado.
dewwwald
2 anos mais tarde, eu ainda lutam em questões semelhantes ...
Frank Nocke
sua atualização deve ser uma resposta, +1
Z. Khullah

Respostas:

82

Esta resposta pode ajudar. Executores de tarefas (Gulp, Grunt, etc) e Empacotadores (Webpack, Browserify). Por que usar juntos?

... e aqui está um exemplo de uso do webpack a partir de uma tarefa gulp. Isso vai um passo além e assume que sua configuração do webpack está escrita em 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();
            }
        }
    }
}

Acho que você descobrirá que, à medida que seu aplicativo se torna mais complicado, convém usar o gulp com uma tarefa de webpack, como no exemplo acima. Isso permite que você faça mais algumas coisas interessantes em sua compilação que os carregadores e plugins da Webpack realmente não fazem, ou seja. criando diretórios de saída, iniciando servidores etc. Bem, para ser sucinto, o webpack pode realmente fazer essas coisas, mas você pode encontrá-las limitadas para suas necessidades de longo prazo. Uma das maiores vantagens que você obtém do gulp -> webpack é que você pode personalizar sua configuração do webpack para diferentes ambientes e fazer com que o gulp faça a tarefa certa na hora certa. Depende de você, mas não há nada de errado em executar o webpack a partir do gulp, na verdade existem alguns exemplos bem interessantes de como fazê-lo. .

4m1r
fonte
Meu projeto do webpack é muito grande - portanto, preciso aumentar a memória do nó também através da linha de comando stackoverflow.com/questions/34727743/… Existe alguma maneira de fazer isso diretamente via webpack?
Abhinav Singi
Confira esses dois. Você provavelmente precisará configurar a memória v8 antes de executar o nó ou o webpack. stackoverflow.com/questions/7193959/… e webpack.github.io/docs/build-performance.html
4m1r
Não sei por que aceitei isso como resposta. Suponho que provavelmente foi devido ao primeiro link que você compartilhou. Mas usando o webpack da gulp? isso é ainda mais complicado se você me perguntar agora :). Eu nem tentaria recorrer a algo assim.
PositiveGuy
80

Os scripts do NPM podem fazer o mesmo que o gulp, mas com cerca de 50x menos código. De fato, sem nenhum código, apenas argumentos de linha de comando.

Por exemplo, o caso de uso que você descreveu onde deseja ter código diferente para diferentes ambientes.

Com os scripts Webpack + NPM, é 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/*\"",

Agora você simplesmente mantém dois scripts de configuração do webpack, um para o modo de desenvolvimento webpack.development.jse outro para o modo de produção webpack.production.js. Também utilizo um webpack.common.jsque hospeda a configuração do webpack compartilhada em todos os ambientes e uso o webpackMerge para mesclá-los.

Devido à frescura dos scripts do NPM, ele permite um encadeamento fácil, semelhante ao modo como o Gulp faz o Streams / pipes.

No exemplo acima, para construir para o desenvolvimento, basta acessar a linha de comando e executar npm run build:dev.

  1. NPM seria executado primeiro prebuild:dev,
  2. então build:dev,
  3. E, finalmente postbuild:dev.

Os prefixos pree postinformam ao NPM em que ordem executar.

Se você observar, com os scripts Webpack + NPM, é possível executar programas nativos, como rimraf, em vez de um gulp-wrapper para um programa nativo, como gulp-rimraf. Você também pode executar arquivos .exe nativos do Windows, como eu fiz aqui comelevate.exe ou arquivos * nix nativos no Linux ou Mac.

Tente fazer a mesma coisa com gole. Você terá que esperar alguém aparecer e escrever um gulp-wrapper para o programa nativo que você deseja usar. Além disso, você provavelmente precisará escrever um código complicado como este: (extraído diretamente do repositório angular2-seed )

Código de desenvolvimento 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 produção de gole

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

O código gulp atual é muito mais complicado que isso, pois esse é apenas dois dos vários arquivos gulp presentes no repositório.

Então, qual é mais fácil para você?

Na minha opinião, os scripts do NPM superam em muito o gulp e o grunhido, tanto em eficácia quanto em facilidade de uso, e todos os desenvolvedores de front-end devem considerar usá-lo em seu fluxo de trabalho, pois economiza muito tempo.

ATUALIZAR

Há um cenário que encontrei em que queria usar o Gulp em combinação com scripts NPM e Webpack.

Quando preciso fazer depuração remota em um dispositivo iPad ou Android, por exemplo, preciso iniciar servidores extras. No passado, eu executei todos os servidores como processos separados, no IntelliJ IDEA (ou Webstorm), que é fácil com a Configuração de Execução "Composta". Mas, se eu precisar parar e reiniciá-los, seria entediante fechar cinco guias de servidor diferentes, além de a saída estar espalhada pelas diferentes janelas.

Um dos benefícios do gulp é que é possível encadear toda a saída de processos independentes separados em uma janela do console, que se torna o pai de todos os servidores filhos.

Então, criei uma tarefa gulp muito simples que apenas executa meus scripts do NPM ou os comandos diretamente, para que toda a saída apareça em uma janela e eu possa finalizar facilmente todos os 5 servidores de uma só vez, fechando a janela da tarefa 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'));

Ainda é um pouco de código apenas para executar 5 tarefas, na minha opinião, mas funciona para esse fim. Uma ressalva é que gulp-shellparece não executar alguns comandos corretamente, como ios-webkit-debug-proxy. Então eu tive que criar um script NPM que apenas execute o mesmo comando e funcione.

Portanto, eu uso principalmente scripts NPM para todas as minhas tarefas, mas, ocasionalmente, quando preciso executar vários servidores de uma só vez, inicio minha tarefa Gulp para ajudar. Escolha a ferramenta certa para o trabalho certo.

ATUALIZAÇÃO 2

Agora eu uso um script chamado simultaneamente, que faz a mesma coisa que a tarefa gulp acima. Ele executa vários scripts da CLI em paralelo e canaliza todos eles para a mesma janela do console, e é muito simples de usar. Mais uma vez, nenhum código é necessário (bem, o código está dentro do node_module simultaneamente, mas você não precisa se preocupar com isso)

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

Isso executa todos os 5 scripts em paralelo canalizados para um terminal. Impressionante! Portanto, neste ponto, raramente uso o gulp, pois existem muitos scripts cli para executar as mesmas tarefas sem código.

Eu sugiro que você leia esses artigos que os comparam em profundidade.

TetraDev
fonte
14
Isso é porque suas tarefas são relativamente fáceis. Boa sorte complexo scripting constrói com shell :-)
Filip Sobczak
5
Estes são apenas exemplos. Minha compilação é muito complexa e possui muitos scripts em execução no shell, funciona perfeitamente e é fácil de manter. E, o que os scripts NPM não fazem por mim, o webpack faz, como uglify, compactar gzip, transform, etc. Obrigado. O que é tão complexo que você precisa para engolir?
TetraDev 19/10/2016
2
(mais de um ano depois, lol): muito obrigado, excelente resposta !!
PositiveGuy
1
@ user108471 Claro que o webpack pode, ele pode criar um assets.json que lista todos os módulos compilados com os IDs associados. Muitos outros tipos de arquivos JSON de informações em tempo de construção podem ser criados com os plugins corretos. Que tipo especificamente você está se referindo a esse gole?
TetraDev 13/06/19
1
@GiannosCharalambous Obrigado por essa dica. Estou usando npm-run-allhá alguns meses, mas nem pensei em usar a -pbandeira paralela! Vou tentar isso esta semana
TetraDev 04/02
8

Eu usei as duas opções em meus projetos diferentes.

Aqui é um clichê que eu coloquei em conjunto, utilizando gulpcom webpack- https://github.com/iroy2000/react-reflux-boilerplate-with-webpack .

Eu tenho algum outro projeto usado apenas webpackcom npm tasks.

E os dois funcionam totalmente bem. E eu acho que é muito complicado como sua tarefa é e quanto controle você deseja ter em sua configuração.

Por exemplo, se você tarefas é simples, digamos dev, build, test... etc (que é muito normal), você está totalmente bem com apenas simples webpackcom npm tasks.

Mas se você tiver um fluxo de trabalho muito complicado e quiser ter mais controle de sua configuração (porque está codificando), poderá optar pela rota gulp.

Mas, de acordo com minha experiência, o ecossistema webpack fornece plug-ins e carregadores mais do que suficientes, e por isso adoro usar a abordagem mínima, a menos que haja algo que você possa fazer apenas no gulp. Além disso, facilitará sua configuração se você tiver menos uma coisa no seu sistema.

E muitas vezes, hoje em dia, vejo pessoas substituindo gulp and browsifytodas juntas webpacksozinhas.

RR
fonte
5
Sim, mas o Webpack tem uma má reputação de ser muito complicado de entender. Costumo tentar usar o gulp primeiro com o browserify, ainda não estou pronto para assumir o Webpack e, em parte, ainda não fiz muito com o Browserify ou o nó no front-end, por isso, quero aprender como todo mundo faz isso com o gulp e browserify primeiro, só assim eu tenho essa história em termos de experiência
PositiveGuy
1
O Webpack só é complicado se você não tiver trabalhado com ele, como gulp, grun, browserify, datilografado e qualquer outra coisa. O Webpack é extremamente fácil de usar depois que você entender como configurar o arquivo de configuração e trabalhar com carregadores. De fato, os arquivos de configuração podem ter até 20 a 30 linhas de código para uma compilação do webpack em funcionamento e podem ser tão robustos quanto necessário. Sem mencionar que o Webpack Hot Module Replacement é absolutamente incrível. Veja: andrewhfarmer.com/understanding-hmr e andrewhfarmer.com/webpack-hmr-tutorial e medium.com/@dabit3/beginner-s-guide-to-webpack-b1f1a3638460
TetraDev
2

Os conceitos de Gulp e Webpack são bem diferentes. Você diz ao Gulp como reunir o código do front-end passo a passo, mas diz ao Webpack o que deseja através de um arquivo de configuração.

Aqui está um pequeno artigo (5 min de leitura) que escrevi explicando minha compreensão das diferenças: https://medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack-c45671ad87fe

Nossa empresa mudou-se de Gulp para Webpack no ano passado. Embora tenha levado algum tempo, descobrimos como mover tudo o que fizemos no Gulp para o Webpack. Então, para nós, tudo o que fizemos no Gulp também podemos fazer através do Webpack, mas não o contrário.

A partir de hoje, sugiro que você use o Webpack e evite a mistura de Gulp e Webpack para que você e sua equipe não precisem aprender e manter os dois, principalmente porque estão exigindo mentalidades muito diferentes.

Maokai
fonte
2

Honestamente, acho que o melhor é usar os dois.

  • Webpack para todos os javascript relacionados.
  • Gole para todos os CSS relacionados.

Ainda tenho que encontrar uma solução decente para empacotar css com webpack, e até agora estou feliz em usar gulp para css e webpack para javascript.

Eu também uso npmscripts como @Tetradev, conforme descrito. Especialmente desde que eu estou usando Visual Studio, e enquanto NPM Task runneré bastante confiável, Webpack Task Runner é bastante complicado .

Max Favilli
fonte
Descobri usando o NPM Task Runner + Gulp a chave. Coloque os comandos webpack no arquivo packange.json e o CSS (SASS) relacionados ao arquivo gulp. Também configurar o package.json ter uma etapa de compilação que chama uma tarefa gole como parte da versão de produção
Nico