Gulp + Webpack oder NUR Webpack?

161

Ich sehe Leute, die Schluck mit Webpack benutzen. Aber dann habe ich gelesen, Webpack kann Schluck ersetzen? Ich bin hier völlig verwirrt ... kann jemand erklären?

AKTUALISIEREN

Am Ende fing ich mit Schlucken an. Ich war neu im modernen Frontend und wollte nur schnell einsatzbereit sein. Jetzt, wo ich nach mehr als einem Jahr meine Füße ziemlich nass habe, bin ich bereit, zum Webpack überzugehen. Ich schlage die gleiche Route für Leute vor, die in den gleichen Schuhen anfangen. Das heißt nicht, dass Sie Webpack nicht ausprobieren können, sondern nur sagen, wenn es kompliziert erscheint, beginnen Sie zuerst mit Schlucken ... daran ist nichts auszusetzen.

Wenn Sie nicht schlucken möchten, gibt es ja ein Grunzen, aber Sie können auch einfach Befehle in Ihrer package.json angeben und sie über die Befehlszeile ohne einen Task-Runner aufrufen, um zunächst einsatzbereit zu sein. Beispielsweise:

"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
quelle
3
Dies hat mir geholfen, Webpack besser zu verstehen als Webpacks eigene Dokumente oder Artikel: github.com/petehunt/webpack-howto
George Ananda Eman
blog.andrewray.me/webpack-when-to-use-and-why keine Notwendigkeit, Schluck mit Webpack zu verwenden
Andy Ray
Mein einfaches Beispiel wäre, dass der Webpack-Dev-Server meine JS mit HMR verarbeiten soll, aber ich habe Probleme, bei denen ich keine statischen Site-Generatoren und keinen Webpack-Dev-Server verwenden kann. Mit komplizierter Konfiguration kann ich dies erreichen, aber es ist ein einfacher Schluck, ich kann es auch tun. Der Hauptunterschied ist also Zeit und Lernkurve.
Dewwwald
2 Jahre später kämpfe ich immer noch mit ähnlichen Themen ...
Frank Nocke
Ihr Update sollte eine Antwort sein, +1
Z. Khullah

Antworten:

82

Diese Antwort könnte helfen. Task Runners (Gulp, Grunt usw.) und Bundler (Webpack, Browserify). Warum zusammen verwenden?

... und hier ist ein Beispiel für die Verwendung von Webpack innerhalb einer Schluckaufgabe. Dies geht noch einen Schritt weiter und setzt voraus, dass Ihre Webpack-Konfiguration in es6 geschrieben ist.

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

Ich denke, Sie werden feststellen, dass Sie, wenn Ihre App komplizierter wird, möglicherweise gulp mit einer Webpack-Aufgabe verwenden möchten, wie im obigen Beispiel dargestellt. Auf diese Weise können Sie einige weitere interessante Dinge in Ihrem Build tun, die Webpack-Loader und -Plugins wirklich nicht tun, z. Erstellen von Ausgabeverzeichnissen, Starten von Servern usw. Um es kurz zu machen: Webpack kann diese Aufgaben tatsächlich ausführen, aber Sie können feststellen, dass sie für Ihre langfristigen Anforderungen begrenzt sind. Einer der größten Vorteile von gulp -> webpack ist, dass Sie Ihre Webpack-Konfiguration für verschiedene Umgebungen anpassen können und gulp die richtige Aufgabe zur richtigen Zeit ausführen lässt. Es liegt wirklich an Ihnen, aber es ist nichts Falsches daran, Webpack von gulp aus auszuführen. Tatsächlich gibt es einige ziemlich interessante Beispiele dafür. Das obige Beispiel stammt im Wesentlichen von .

4m1r
quelle
Mein Webpack-Projekt ist ziemlich groß - daher muss ich den Knotenspeicher auch über den Befehlszeilenbefehl stackoverflow.com/questions/34727743/… erhöhen. Gibt es eine Möglichkeit, dies direkt über das Webpack zu tun?
Abhinav Singi
Schauen Sie sich diese beiden an. Sie müssen wahrscheinlich v8-Speicher einstellen, bevor Sie Node oder Webpack ausführen. stackoverflow.com/questions/7193959/… und webpack.github.io/docs/build-performance.html
4m1r
Ich bin mir nicht sicher, warum ich das als Antwort akzeptiert habe. Ich nehme an, es lag wahrscheinlich an dem ersten Link, den Sie geteilt haben. Aber mit Webpack von gulp? Das ist noch mehr ein Chaos, wenn du mich jetzt fragst :). Ich würde nicht einmal versuchen, auf so etwas zurückzugreifen.
PositiveGuy
80

NPM-Skripte können dasselbe wie gulp tun, jedoch mit etwa 50-mal weniger Code. In der Tat, ohne Code, nur Befehlszeilenargumente.

Beispiel: Der von Ihnen beschriebene Anwendungsfall, in dem Sie unterschiedlichen Code für unterschiedliche Umgebungen verwenden möchten.

Mit Webpack + NPM-Skripten ist das ganz einfach:

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

Jetzt verwalten Sie einfach zwei Webpack-Konfigurationsskripte, eines für den Entwicklungsmodus webpack.development.jsund eines für den Produktionsmodus webpack.production.js. Ich verwende auch eine webpack.common.jsWebpack-Konfiguration, die in allen Umgebungen gemeinsam genutzt wird, und verwende webpackMerge, um sie zusammenzuführen.

Aufgrund der Coolness von NPM-Skripten ermöglicht es eine einfache Verkettung, ähnlich wie bei gulp Streams / Pipes.

Im obigen Beispiel gehen Sie zum Erstellen für die Entwicklung einfach zu Ihrer Befehlszeile und führen sie aus npm run build:dev.

  1. NPM würde zuerst laufen prebuild:dev,
  2. dann build:dev,
  3. Und schließlich postbuild:dev.

Die Präfixe preund postteilen NPM mit, in welcher Reihenfolge sie ausgeführt werden sollen.

Wenn Sie feststellen, dass Sie mit Webpack + NPM-Skripten ein natives Programm ausführen können, z. B. rimrafanstelle eines Gulp-Wrappers für ein natives Programm wie z gulp-rimraf. Sie können auch native Windows .exe-Dateien wie hier mit elevate.exeoder native * nix-Dateien unter Linux oder Mac ausführen .

Versuchen Sie, dasselbe mit Schluck zu tun. Sie müssen warten, bis jemand kommt und einen Schluck-Wrapper für das native Programm schreibt, das Sie verwenden möchten. Außerdem müssen Sie wahrscheinlich verschachtelten Code wie folgt schreiben: (direkt aus dem Angular2-Seed- Repo entnommen )

Gulp Entwicklungscode

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 Produktionscode

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

Der eigentliche Gulp-Code ist viel komplizierter als dieser, da dies nur zwei der mehreren Dutzend Gulp-Dateien im Repo sind.

Welches ist für Sie einfacher?

Meiner Meinung nach übertreffen NPM-Skripte in Bezug auf Effektivität und Benutzerfreundlichkeit das Schlucken und Grunzen bei weitem, und alle Front-End-Entwickler sollten in Betracht ziehen, sie in ihrem Workflow zu verwenden, da dies eine erhebliche Zeitersparnis darstellt.

AKTUALISIEREN

Es gibt ein Szenario, in dem ich Gulp in Kombination mit NPM-Skripten und Webpack verwenden wollte.

Wenn ich beispielsweise ein Remote-Debugging auf einem iPad oder Android-Gerät durchführen muss, muss ich zusätzliche Server starten. In der Vergangenheit habe ich alle Server als separate Prozesse innerhalb von IntelliJ IDEA (oder Webstorm) ausgeführt, was mit der "Compound" -Laufkonfiguration einfach ist. Wenn ich sie jedoch stoppen und neu starten muss, war es mühsam, 5 verschiedene Server-Registerkarten schließen zu müssen, und die Ausgabe wurde auf die verschiedenen Fenster verteilt.

Einer der Vorteile von gulp besteht darin, dass die gesamte Ausgabe von separaten unabhängigen Prozessen in einem Konsolenfenster verkettet werden kann, das zum übergeordneten Element aller untergeordneten Server wird.

Daher habe ich eine sehr einfache Gulp-Aufgabe erstellt, die nur meine NPM-Skripte oder die Befehle direkt ausführt, sodass die gesamte Ausgabe in einem Fenster angezeigt wird und ich alle 5 Server gleichzeitig beenden kann, indem ich das Fenster für die Gulp-Aufgabe schließe.

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

Meiner Meinung nach immer noch ziemlich viel Code, um nur 5 Aufgaben auszuführen, aber es funktioniert für diesen Zweck. Eine Einschränkung ist, dass gulp-shelleinige Befehle nicht korrekt ausgeführt werden, z ios-webkit-debug-proxy. Also musste ich ein NPM-Skript erstellen, das nur den gleichen Befehl ausführt, und dann funktioniert es.

Daher verwende ich hauptsächlich NPM-Skripte für alle meine Aufgaben. Wenn ich jedoch gelegentlich mehrere Server gleichzeitig ausführen muss, starte ich meine Gulp-Aufgabe, um zu helfen. Wählen Sie das richtige Werkzeug für den richtigen Job.

UPDATE 2

Ich verwende jetzt ein Skript, das gleichzeitig aufgerufen wird und dasselbe wie die oben beschriebene Schluckaufgabe ausführt. Es führt mehrere CLI-Skripte parallel aus und leitet sie alle an dasselbe Konsolenfenster weiter. Die Verwendung ist sehr einfach. Auch hier ist kein Code erforderlich (nun, der Code befindet sich gleichzeitig im node_module, aber Sie müssen sich nicht darum kümmern)

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

Dadurch werden alle 5 Skripte parallel an ein Terminal weitergeleitet. Genial! Daher verwende ich an diesem Punkt selten gulp, da es so viele CLI-Skripte gibt, um dieselben Aufgaben ohne Code auszuführen.

Ich schlage vor, Sie lesen diese Artikel, die sie ausführlich vergleichen.

TetraDev
quelle
14
Das liegt daran, dass Ihre Aufgaben relativ einfach sind. Viel Glück beim Erstellen von Skripten mit Shell :-)
Filip Sobczak
5
Dies sind nur Beispiele. Mein Build ist sehr komplex und hat viele Skripte, die auf der Shell ausgeführt werden, funktioniert einwandfrei und ist einfach zu warten. Und was NPM-Skripte für mich nicht tun, macht Webpack, wie uglify, komprimieren gzip, transformieren usw. Danke. Was ist so komplex, dass Sie einen Schluck brauchen?
TetraDev
2
(mehr als ein Jahr später lol): Vielen Dank, ausgezeichnete Antwort !!
PositiveGuy
1
@ user108471 Sicher, Webpack kann, es kann eine Assets.json erstellen, die alle Module auflistet, die mit den zugehörigen IDs kompiliert wurden. Mit den richtigen Plugins können viele weitere Arten von Build-Time-Informationen für JSON-Dateien erstellt werden. Welche Art von speziell beziehen Sie sich auf diesen Schluck?
TetraDev
1
@ GiannosCharalambous Danke für diesen Tipp. Ich benutze es tatsächlich seit npm-run-allein paar Monaten, aber ich habe nicht einmal daran gedacht, die -pparallele Flagge zu verwenden! Ich werde das diese Woche
ausprobieren
8

Ich habe beide Optionen in meinen verschiedenen Projekten verwendet.

Hier ist eine Boilerplate, die ich mit zusammengestellt habe gulp mit webpack- https://github.com/iroy2000/react-reflux-boilerplate-with-webpack zusammengestellt habe .

Ich habe ein anderes Projekt nur webpackmit verwendet npm tasks.

Und beide funktionieren völlig gut. Und ich denke, es brennt darauf hinaus, wie kompliziert Ihre Aufgabe ist und wie viel Kontrolle Sie in Ihrer Konfiguration haben möchten.

Wenn Sie Aufgaben einfach ist zum Beispiel, sagen wir mal dev, build, test... usw. (was sehr Standard), sind Sie völlig in Ordnung mit nur einfach webpackmit npm tasks.

Wenn Sie jedoch einen sehr komplizierten Workflow haben und mehr Kontrolle über Ihre Konfiguration haben möchten (weil es sich um eine Codierung handelt), können Sie sich für eine Schluckroute entscheiden.

Aber meiner Erfahrung nach bietet das Webpack-Ökosystem mehr als genug Plugins und Loader, die ich benötige, und deshalb liebe ich es, den absoluten Minimum-Ansatz zu verwenden, es sei denn, es gibt etwas, das Sie nur in gulp tun können. Außerdem wird Ihre Konfiguration einfacher, wenn Sie eine Sache weniger in Ihrem System haben.

Und heutzutage sehe ich oft Leute, die tatsächlich gulp and browsifyalle zusammen mit webpackallein ersetzen .

RR
quelle
5
Ja, aber Webpack hat den schlechten Ruf, zu kompliziert zu verstehen. Ich neige dazu, gulp zuerst mit browserify zu verwenden, bin noch nicht bereit, Webpack zu übernehmen, und teilweise habe ich nicht viel mit Browserify oder Node im Front-End gemacht, also möchte ich lernen, wie jeder es mit gulp und macht browserify zuerst nur damit ich diese Geschichte in Bezug auf Erfahrung habe
PositiveGuy
1
Webpack ist nur dann kompliziert, wenn Sie nicht damit gearbeitet haben, genau wie Schlucken, Grunzen, Browserify, Typoskript und alles andere. Webpack ist äußerst einfach zu bedienen, sobald Sie wissen, wie Sie die Konfigurationsdatei einrichten und mit Loadern arbeiten. Tatsächlich können die Konfigurationsdateien nur 20 bis 30 Codezeilen für einen funktionierenden Webpack-Build enthalten und so robust sein, wie Sie es benötigen. Ganz zu schweigen vom Webpack Hot Module Replacement ist absolut erstaunlich. Siehe: andrewhfarmer.com/understanding-hmr und andrewhfarmer.com/webpack-hmr-tutorial and medium.com/@dabit3/beginner-s-guide-to-webpack-b1f1a3638460
TetraDev
2

Die Konzepte von Gulp und Webpack sind sehr unterschiedlich. Sie teilen Gulp Schritt für Schritt mit, wie Front-End-Code zusammengestellt werden soll, aber Sie teilen Webpack über eine Konfigurationsdatei mit, was Sie möchten.

Hier ist ein kurzer Artikel (5 Minuten gelesen), in dem ich mein Verständnis der Unterschiede erläuterte: https://medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack-c45671ad87fe

Unsere Firma ist im vergangenen Jahr von Gulp zu Webpack gewechselt. Obwohl es einige Zeit gedauert hat, haben wir herausgefunden, wie wir alles, was wir in Gulp getan haben, auf Webpack verschieben können. Für uns ist alles, was wir in Gulp getan haben, auch über Webpack möglich, aber nicht umgekehrt.

Ab heute würde ich vorschlagen, nur Webpack zu verwenden und die Mischung aus Gulp und Webpack zu vermeiden, damit Sie und Ihr Team nicht beide lernen und pflegen müssen, insbesondere weil sie sehr unterschiedliche Denkweisen erfordern.

Maokai
quelle
2

Ehrlich gesagt denke ich, das Beste ist, beide zu verwenden.

  • Webpack für alle Javascript bezogenen.
  • Schluck für alle CSS bezogenen.

Ich muss noch eine anständige Lösung finden, um CSS mit Webpack zu verpacken, und bis jetzt bin ich glücklich, gulp für CSS und Webpack für Javascript zu verwenden.

Ich benutze auch npmSkripte als @Tetradev wie beschrieben. Vor allem, weil ich benutze Visual Studio, und obwohl NPM Task runneres ziemlich zuverlässig Webpack Task Runner ist, ist es ziemlich fehlerhaft .

Max Favilli
quelle
Ich habe mit dem NPM Task Runner + Gulp den Schlüssel gefunden. Fügen Sie die Webpack-Befehle in die Datei packange.json und das zugehörige CSS (SASS) in die gulp-Datei ein. Richten Sie außerdem die Datei package.json so ein, dass ein Build-Schritt ausgeführt wird, der eine Gulp-Task als Teil der Produktionsversion
Nico,