web-dev-qa-db-fra.com

Gulp + Webpack ou JUST Webpack?

Je vois des gens utiliser gulp avec Webpack. Mais alors je lis webpack peut remplacer gulp? Je suis complètement confus ici ... quelqu'un peut-il expliquer?

MISE À JOUR

à la fin j'ai commencé avec gulp. J'étais nouveau sur le front-end moderne et je voulais juste être opérationnel rapidement. Maintenant que j'ai les pieds bien mouillés après plus d'un an, je suis prêt à passer à Webpack. Je suggère le même itinéraire pour les personnes qui commencent dans la même situation. Ne dites pas que vous ne pouvez pas essayer le WebPack, mais dites simplement que si cela vous semble compliqué, commencez par boire en premier ... rien de mal à cela.

Si vous ne voulez pas gulp, oui, il y a grunt, mais vous pouvez également spécifier des commandes dans votre package.json et les appeler à partir de la ligne de commande sans un programme de gestion de tâches, juste pour être opérationnel au départ. Par exemple:

"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"
    },
147
PositiveGuy

Cette réponse pourrait aider. Task Runners (Gulp, Grunt, etc.) et Bundlers (Webpack, Browserify). Pourquoi utiliser ensemble?

... et voici un exemple d'utilisation de webpack à partir d'une tâche gulp. Cela va un peu plus loin et suppose que votre configuration webpack est écrite 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();
            }
        }
    }
}

Je pense que vous constaterez que plus votre application devient compliquée, vous pouvez utiliser gulp avec une tâche webpack, comme dans l'exemple ci-dessus. Cela vous permet de faire quelques choses plus intéressantes dans votre construction que les chargeurs de packs Web et les plugins ne font vraiment pas, par exemple. créer des répertoires de sortie, démarrer des serveurs, etc. Eh bien, pour résumer, webpack peut faire ce genre de choses, mais vous pourriez les trouver limitées pour vos besoins à long terme. L'un des principaux avantages de gulp -> webpack est que vous pouvez personnaliser votre configuration Webpack pour différents environnements et que gulp effectue la bonne tâche au bon moment. C’est vraiment à vous de décider, mais il n’ya rien de mal à utiliser Webpack depuis gulp. En fait, il existe quelques jolis intéressants exemples de la façon de le faire. L'exemple ci-dessus est essentiellement de jlongster .

77
4m1r

Les scripts NPM peuvent faire la même chose que gulp, mais environ 50 fois moins de code. En fait, sans code du tout, seulement des arguments en ligne de commande.

Par exemple, le cas d'utilisation que vous avez décrit pour lequel vous souhaitez avoir un code différent pour différents environnements.

Avec les scripts Webpack + NPM, rien de plus simple:

"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/*\"",

Maintenant, vous gérez simplement deux scripts de configuration webpack, un pour le mode de développement, webpack.development.js, et un pour le mode de production, webpack.production.js. J'utilise également un webpack.common.js qui héberge la configuration de Webpack partagée sur tous les environnements, et j'utilise WebpackMerge pour les fusionner.

En raison de la fraîcheur des scripts NPM, il permet un chaînage facile, similaire à la façon dont gulp fait Stream/pipes.

Dans l'exemple ci-dessus, pour construire en vue du développement, il vous suffit d'accéder à votre ligne de commande et d'exécuter npm run build:dev.

  1. NPM lancera d'abord prebuild:dev,
  2. Alors build:dev,
  3. Et enfin postbuild:dev.

Les préfixes pre et post indiquent au NPM quel ordre exécuter.

Si vous remarquez, avec les scripts Webpack + NPM, vous pouvez exécuter un programme natif, tel que rimraf, au lieu d'un encapsuleur pour un programme natif tel que gulp-rimraf. Vous pouvez également exécuter des fichiers Windows .exe natifs comme je l’ai fait ici avec elevate.exe ou des fichiers natifs * nix sous Linux ou Mac.

Essayez de faire la même chose avec gulp. Vous devrez attendre que quelqu'un vienne et écrive un gulp-wrapper pour le programme natif que vous souhaitez utiliser. De plus, vous aurez probablement besoin d'écrire du code compliqué comme ceci: (tiré directement de angular2-seed repo)

Code de développement 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));
};

Gulp Code de production

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

Le code gulp est bien plus compliqué que cela, car il ne s'agit que de deux des plusieurs dizaines de fichiers gulp du référentiel.

Alors, lequel est le plus facile pour vous?

À mon avis, les scripts NPM surpassent de loin les avantages, tant du point de vue de l'efficacité que de la simplicité d'utilisation, et tous les développeurs front-end devraient envisager de les utiliser dans leur flux de travail, car ils permettent de gagner beaucoup de temps.

UPDATE

J'ai rencontré un scénario dans lequel je souhaitais utiliser Gulp en combinaison avec des scripts NPM et Webpack.

Lorsque je dois effectuer un débogage distant sur un iPad ou un périphérique Android, par exemple, je dois démarrer des serveurs supplémentaires. Dans le passé, j’exécutais tous les serveurs en tant que processus distincts, depuis IntelliJ IDEA (Ou Webstorm), ce qui est simple avec la configuration d’exécution "Compound". Mais si j’avais besoin de les arrêter et de les redémarrer, il était fastidieux de fermer 5 onglets de serveur différents, et le résultat était réparti entre les différentes fenêtres.

L'un des avantages de gulp est qu'il est possible de chaîner toutes les sorties de processus indépendants dans une fenêtre de console unique, qui devient le parent de tous les serveurs enfants.

J'ai donc créé une tâche gulp très simple qui exécute directement les scripts ou les commandes NPM, de sorte que toutes les sorties apparaissent dans une fenêtre. Je peux facilement terminer les 5 serveurs en même temps en fermant la fenêtre de la tâche 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'));

Encore un peu de code juste pour exécuter 5 tâches, à mon avis, mais cela fonctionne dans ce but. Un inconvénient est que gulp-Shell ne semble pas exécuter certaines commandes correctement, tel que ios-webkit-debug-proxy. J'ai donc dû créer un script NPM exécutant simplement la même commande, puis tout fonctionne.

J'utilise donc principalement les scripts NPM pour toutes mes tâches, mais parfois, lorsque je dois exécuter plusieurs serveurs à la fois, je lance ma tâche Gulp pour vous aider. Choisissez le bon outil pour le bon travail.

UPDATE 2

J'utilise maintenant un script appelé en même temps qui fait la même chose que la tâche gulp ci-dessus. Il exécute plusieurs scripts CLI en parallèle et les redirige tous vers la même fenêtre de console, ce qui est très simple à utiliser. Encore une fois, aucun code requis (eh bien, le code se trouve à l'intérieur du nœud_module pour simultanément, mais vous n'avez pas à vous en préoccuper)

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

Ceci exécute tous les 5 scripts en parallèle redirigés vers un terminal. Impressionnant! Ainsi, j’utilise rarement gulp, car il ya tellement de scripts cli pour effectuer les mêmes tâches sans code.

Je vous suggère de lire ces articles qui les comparent en profondeur.

77
TetraDev

J'ai utilisé les deux options dans mes différents projets.

Voici un passe-partout que j'ai assemblé en utilisant gulp avec webpack - https://github.com/iroy2000/react-reflux-boilerplate-with-webpack .

J'ai un autre projet utilisé uniquement webpack avec npm tasks.

Et ils fonctionnent parfaitement. Et je pense qu’il est difficile de comprendre à quel point votre tâche est compliquée et quel contrôle vous souhaitez avoir dans votre configuration.

Par exemple, si vos tâches sont simples, supposons que dev, build, test ... etc (ce qui est très standard), vous êtes parfaitement satisfait avec les simples webpack avec npm tasks.

Mais si vous avez un flux de travail très compliqué et que vous souhaitez avoir plus de contrôle sur votre configuration (parce qu’elle est en train de coder), vous pouvez opter pour la route gulp.

Mais de par mon expérience, l'écosystème webpack fournit plus que suffisamment de plugins et de chargeurs dont j'ai besoin, et j'aime donc utiliser l'approche du strict minimum, à moins que vous ne puissiez faire quelque chose que gulp. Et aussi, cela facilitera votre configuration si vous avez un élément de moins dans votre système.

Et souvent, je vois maintenant des gens remplacer gulp and browsify ensemble par webpack seul.

8
R.R

Honnêtement, je pense que le mieux est d'utiliser les deux.

  • Webpack pour tous javascript connexes.
  • Gulp pour tous css connexes.

Je dois encore trouver une solution décente pour empaqueter des CSS avec WebPack, et je suis heureux d’avoir utilisé gulp pour CSS et WebPack pour JavaScript.

J'utilise aussi les scripts npm comme @Tetradev comme décrit. Surtout que j'utilise Visual Studio, et que NPM Task runner est joli fiableWebpack Task Runner est joli buggy.

2
Max Favilli

Les concepts de Gulp et Webpack sont assez différents. Vous dites à Gulp comment assembler pas à pas le code frontal, mais vous indiquez à Webpack quoi vous voulez via un fichier de configuration.

Voici un court article (5 min de lecture) que j'ai écrit pour expliquer ma compréhension des différences: https://medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack- c45671ad87fe

Notre société est passée de Gulp à Webpack au cours de la dernière année. Bien que cela ait pris un peu de temps, nous avons trouvé comment déplacer tout ce que nous avons fait à Gulp vers Webpack. Donc, pour nous, tout ce que nous avons fait à Gulp peut également être fait via Webpack, mais pas l’inverse.

À compter d’aujourd’hui, je suggérerais simplement d’utiliser Webpack et d’éviter le mélange de Gulp et Webpack afin que vous et votre équipe n’ayez pas besoin d’apprendre et de maintenir les deux, en particulier parce qu’ils nécessitent des mentalités très différentes.

1
Maokai