Gulp + Webpack czy JUST Webpack?

161

Widzę ludzi używających łyka z webpackiem. Ale potem przeczytałem, że webpack może zastąpić łyk? Jestem tu całkowicie zdezorientowany ... czy ktoś może wyjaśnić?

AKTUALIZACJA

w końcu zacząłem od łyka. Byłem nowy w nowoczesnym interfejsie i po prostu chciałem szybko zacząć działać. Teraz, gdy po ponad roku mam mokre stopy, jestem gotowy, aby przejść do webpacka. Proponuję tę samą trasę dla osób zaczynających w tych samych butach. Nie mówię, że nie możesz spróbować webpacka, ale po prostu powiedz, jeśli wydaje się to skomplikowane, zacznij od łyka ... nie ma w tym nic złego.

Jeśli nie chcesz łykać, tak, jest chrząknięcie, ale możesz także po prostu określić polecenia w swoim pliku package.json i wywołać je z wiersza poleceń bez modułu uruchamiającego zadania, aby początkowo rozpocząć pracę. Na przykład:

"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
źródło
3
Pomogło mi to lepiej zrozumieć Webpack niż własne dokumenty Webpacka lub jakikolwiek artykuł: github.com/petehunt/webpack-howto
George Ananda Eman
blog.andrewray.me/webpack-when-to-use-and-why nie trzeba używać łyka z webpackiem
Andy Ray
Moim prostym przykładem jest to, że chcę, aby serwer webpack-dev-server obsługiwał mój js za pomocą HMR, ale mam problemy, w których nie mogę używać statycznych generatorów witryn i serwera deweloperskiego pakietu webpack. Dzięki skomplikowanej konfiguracji mogę to osiągnąć, ale jest to proste, mogę to zrobić. Więc główną różnicą jest czas i krzywa uczenia się.
dewwwald,
2 lata później wciąż
zmagam się
Twoja aktualizacja powinna być odpowiedzią, +1
Z. Khullah

Odpowiedzi:

82

Ta odpowiedź może pomóc. Biegacze zadań (Gulp, Grunt itp.) I Pakowacze (Webpack, Browserify). Dlaczego używać razem?

... a oto przykład użycia webpacka z jednego łyka zadania. To idzie o krok dalej i zakłada, że ​​konfiguracja twojego webpacka jest zapisana w 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();
            }
        }
    }
}

Myślę, że przekonasz się, że gdy twoja aplikacja stanie się bardziej skomplikowana, możesz chcieć użyć łyka z zadaniem webpacka, jak na powyższym przykładzie. Pozwala to na zrobienie w kompilacji kilku ciekawszych rzeczy, których programy ładujące i wtyczki webpack naprawdę nie robią, np. tworzenie katalogów wyjściowych, uruchamianie serwerów itp. Cóż, mówiąc zwięźle, webpack faktycznie może robić te rzeczy, ale może się okazać, że są one ograniczone do twoich długoterminowych potrzeb. Jedną z największych zalet gulp -> webpack jest to, że możesz dostosować konfigurację pakietu webpack do różnych środowisk i pozwolić, aby łyk wykonał właściwe zadanie we właściwym czasie. To naprawdę zależy od ciebie, ale nie ma nic złego w uruchamianiu webpacka z łyka, w rzeczywistości jest kilka interesujących przykładów, jak to zrobić..

4m1r
źródło
Mój projekt webpacka jest dość duży - więc muszę zwiększyć pamięć węzła również za pomocą stackoverflow.com/questions/34727743/ wiersza poleceń wiersza poleceń. Czy jest jakiś sposób, aby to zrobić bezpośrednio przez webpack?
Abhinav Singi
Sprawdź te dwa. Prawdopodobnie będziesz musiał ustawić pamięć v8 przed uruchomieniem node lub webpacka. stackoverflow.com/questions/7193959/… i webpack.github.io/docs/build-performance.html
4m1r
Nie jestem pewien, dlaczego zaakceptowałem to jako odpowiedź. Przypuszczam, że było to prawdopodobnie spowodowane pierwszym udostępnionym linkiem. Ale używając webpacka z łyka? to jeszcze większy bałagan, jeśli mnie teraz zapytasz :). Nie próbowałbym nawet uciekać się do czegoś takiego.
PositiveGuy
80

Skrypty NPM mogą robić to samo, co gulp, ale zawierają około 50 razy mniej kodu. W rzeczywistości bez żadnego kodu, tylko argumenty wiersza poleceń.

Na przykład opisany przypadek użycia, w którym chcesz mieć inny kod dla różnych środowisk.

Dzięki skryptom Webpack + NPM jest to takie proste:

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

Teraz po prostu utrzymać dwa skrypty WebPack config, po jednym dla trybu rozwoju, webpack.development.jsi jeden dla trybu produkcyjnego webpack.production.js. Używam również pliku, webpack.common.jsktóry zawiera konfigurację pakietu webpack udostępnioną we wszystkich środowiskach i używam webpackMerge do ich scalania.

Ze względu na fajność skryptów NPM pozwala na łatwe łączenie w łańcuch, podobnie jak gulp robi Strumienie / rury.

W powyższym przykładzie, aby zbudować do programowania, po prostu przejdź do wiersza poleceń i wykonaj npm run build:dev.

  1. NPM będzie najpierw uruchamiany prebuild:dev,
  2. następnie build:dev,
  3. I wreszcie postbuild:dev.

preI postprefiksy powiedzieć KMP jakiej kolejności wykonywać w.

Jeśli zauważysz, dzięki skryptom Webpack + NPM możesz uruchamiać programy natywne, takie jak rimraf, zamiast opakowania gulp dla programu natywnego, takiego jak gulp-rimraf. Możesz także uruchamiać natywne pliki .exe systemu Windows, tak jak tutaj, elevate.exelub natywne pliki * nix w systemie Linux lub Mac.

Spróbuj zrobić to samo z łykiem. Będziesz musiał poczekać, aż ktoś przyjdzie i napisze opakowanie dla natywnego programu, którego chcesz użyć. Ponadto prawdopodobnie będziesz musiał napisać zawiły kod w następujący sposób: (pobrany bezpośrednio z repozytorium angular2-seed )

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

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

Rzeczywisty kod gulp jest znacznie bardziej skomplikowany, ponieważ to tylko 2 z kilkudziesięciu plików gulp w repozytorium.

Więc który z nich jest dla Ciebie łatwiejszy?

Moim zdaniem skrypty NPM znacznie przewyższają łyk i chrząknięcie, zarówno pod względem skuteczności, jak i łatwości użycia, a wszyscy programiści front-end powinni rozważyć użycie go w swoim przepływie pracy, ponieważ jest to duża oszczędność czasu.

AKTUALIZACJA

Jest jeden scenariusz, z którym się spotkałem, w którym chciałem użyć Gulp w połączeniu ze skryptami NPM i Webpack.

Kiedy muszę przeprowadzić zdalne debugowanie na przykład na iPadzie lub urządzeniu z Androidem, muszę uruchomić dodatkowe serwery. W przeszłości uruchamiałem wszystkie serwery jako oddzielne procesy z poziomu IntelliJ IDEA (lub Webstorm), co jest łatwe dzięki „złożonej” konfiguracji uruchamiania. Ale jeśli muszę je zatrzymać i ponownie uruchomić, zamknięcie 5 różnych kart serwera było żmudne, a dane wyjściowe były rozproszone w różnych oknach.

Jedną z zalet gulp jest to, że można połączyć wszystkie dane wyjściowe z oddzielnych niezależnych procesów w jednym oknie konsoli, które staje się nadrzędnym dla wszystkich serwerów podrzędnych.

Stworzyłem więc bardzo proste zadanie typu „łyk”, które po prostu uruchamia moje skrypty NPM lub polecenia bezpośrednio, dzięki czemu wszystkie dane wyjściowe pojawiają się w jednym oknie i mogę łatwo zamknąć wszystkie 5 serwerów jednocześnie, zamykając okno zadania „łyk”.

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

Wciąż całkiem sporo kodu tylko do wykonania 5 zadań, moim zdaniem, ale działa w tym celu. Jedynym zastrzeżeniem jest to, że gulp-shellniektóre polecenia, takie jakios-webkit-debug-proxy . Musiałem więc stworzyć skrypt NPM, który po prostu wykonuje to samo polecenie, a potem działa.

Dlatego przede wszystkim używam skryptów NPM do wszystkich moich zadań, ale czasami, gdy potrzebuję uruchomić kilka serwerów jednocześnie, uruchamiam zadanie Gulp, aby pomóc. Wybierz odpowiednie narzędzie do odpowiedniej pracy.

AKTUALIZACJA 2

Teraz używam skryptu o nazwie concurrently, który robi to samo, co powyższe zadanie łyka. Uruchamia równolegle wiele skryptów CLI i przesyła je wszystkie do tego samego okna konsoli i jest bardzo prosty w użyciu. Ponownie, nie jest wymagany żaden kod (cóż, kod znajduje się w module node_module do jednoczesnego, ale nie musisz się tym przejmować)

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

To uruchamia wszystkie 5 skryptów równolegle do jednego terminala. Niesamowite! Dlatego rzadko używam łyka, ponieważ jest tak wiele skryptów CLI do wykonywania tych samych zadań bez kodu.

Proponuję przeczytać te artykuły, które szczegółowo je porównują.

TetraDev
źródło
14
To dlatego, że twoje zadania są stosunkowo łatwe. Powodzenia w tworzeniu złożonych skryptów z powłoką :-)
Filip Sobczak
5
To są tylko przykłady. Moja kompilacja jest bardzo złożona i zawiera wiele skryptów wykonywanych w powłoce, działa bezbłędnie i jest łatwa w utrzymaniu. I czego nie robią skrypty NPM, to webpack, takie jak uglify, kompresja gzip, transformacja itp. Dzięki. Co jest tak skomplikowane, że potrzebujesz łyka?
TetraDev
2
(ponad rok później lol): wielkie dzięki, świetna odpowiedź !!
PositiveGuy
1
@ user108471 Oczywiście pakiet webpack może, ale może utworzyć plik asset.json zawierający listę wszystkich modułów skompilowanych z powiązanymi identyfikatorami. Za pomocą odpowiednich wtyczek można utworzyć wiele innych typów plików JSON z informacjami o czasie kompilacji. Jaki konkretnie masz na myśli ten łyk?
TetraDev
1
@GiannosCharalambous Dzięki za tę wskazówkę. Właściwie używam npm-run-allod kilku miesięcy, ale nawet nie pomyślałem o użyciu -pflagi równoległej! Spróbuję tego w tym tygodniu
TetraDev
8

Użyłem obu opcji w moich różnych projektach.

Oto jeden szablon, gulpz którym korzystam webpack- https://github.com/iroy2000/react-reflux-boilerplate-with-webpack .

Mam inny projekt używany tylko webpackz npm tasks.

I oba działają całkowicie dobrze. I myślę, że sprowadza się to do tego, jak skomplikowane jest twoje zadanie i jak dużą kontrolę chcesz mieć w swojej konfiguracji.

Na przykład, jeśli zadania jest prosta, powiedzmy dev, build, test... etc (co jest bardzo standardowe), jesteś całkowicie w porządku tylko proste webpackz npm tasks.

Ale jeśli masz bardzo skomplikowany przepływ pracy i chcesz mieć większą kontrolę nad swoją konfiguracją (ponieważ jest to kodowanie), możesz wybrać trasę łykiem.

Ale z mojego doświadczenia wynika, że ​​ekosystem webpacka zapewnia więcej niż wystarczającą liczbę wtyczek i programów ładujących, których będę potrzebować, dlatego uwielbiam stosować podejście minimum, chyba że jest coś, co można zrobić tylko jednym haustem. Ułatwi to również konfigurację, jeśli masz o jedną rzecz mniej w swoim systemie.

Obecnie często widzę, jak ludzie zastępują gulp and browsifywszystko webpacksamemu.

RR
źródło
5
Tak, ale Webpack ma złą reputację, ponieważ jest zbyt trudny do zrozumienia. Zwykle próbuję najpierw użyć gulpa z browserify, nie jestem jeszcze gotowy na przyjęcie Webpacka i częściowo nie zrobiłem zbyt wiele z Browserify lub węzłem na froncie, więc chcę się dowiedzieć, jak wszyscy robią to za pomocą łyka i browserify first, więc mam tę historię pod względem doświadczenia
PositiveGuy
1
Webpack jest skomplikowany tylko wtedy, gdy z nim nie pracowałeś, tak jak łyk, grunt, przeglądarka, maszynopis i cokolwiek innego. Webpack jest niezwykle łatwy w użyciu, gdy zrozumiesz, jak skonfigurować plik konfiguracyjny i pracować z programami ładującymi. W rzeczywistości pliki konfiguracyjne mogą być tak krótkie, jak 20-30 linii kodu dla działającego pakietu webpacka i mogą być tak solidne, jak potrzebujesz. Nie wspominając o wymianie Hot Module Webpack jest absolutnie niesamowite. Zobacz: andrewhfarmer.com/understanding-hmr and andrewhfarmer.com/webpack-hmr-tutorial and medium.com/@dabit3/beginner-s-guide-to-webpack-b1f1a3638460
TetraDev
2

Koncepcje Gulp i Webpack są zupełnie inne. Mówisz Gulpowi, jak krok po kroku połączyć kod front-end, ale mówisz Webpack, czego chcesz, za pomocą pliku konfiguracyjnego.

Oto krótki artykuł (5 minut czytania), który napisałem, wyjaśniając moje rozumienie różnic: https://medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack-c45671ad87fe

Nasza firma przeniosła się z Gulp do Webpack w zeszłym roku. Chociaż zajęło to trochę czasu, zorientowaliśmy się, jak przenieść wszystko, co zrobiliśmy w Gulp do Webpack. Więc dla nas wszystko, co zrobiliśmy w Gulp, możemy również zrobić przez Webpack, ale nie na odwrót.

Na dzień dzisiejszy sugerowałbym po prostu używanie Webpacka i unikanie mieszania Gulp i Webpack, abyście Ty i Twój zespół nie musieliście uczyć się i utrzymywać obu, zwłaszcza, że ​​wymagają one bardzo różnych nastawień.

Maokai
źródło
2

Szczerze mówiąc, myślę, że najlepiej jest używać obu.

  • Pakiet sieciowy dla wszystkich związanych z JavaScriptem .
  • Łyk dla wszystkich związanych z CSS .

Nadal muszę znaleźć przyzwoite rozwiązanie do pakowania css za pomocą webpacka i do tej pory cieszę się, że używam gulp dla css i webpack dla javascript.

Używam również npmskryptów jako @Tetradev zgodnie z opisem. Zwłaszcza, że ​​używam Visual Studioi chociaż NPM Task runnerjest całkiem niezawodny, Webpack Task Runner jest dość wadliwy .

Max Favilli
źródło
Znalazłem klucz za pomocą NPM Task Runner + Gulp. Umieść polecenia pakietu webpack w pliku packange.json, a związany z nim CSS (SASS) w pliku gulp. Skonfiguruj również plik package.json tak, aby zawierał krok kompilacji, który wywołuje zwykłe zadanie jako część wydania produkcyjnego
Nico