簡體   English   中英

Gulp + Webpack 還是 JUST Webpack?

[英]Gulp + Webpack or JUST Webpack?

我看到有人在 webpack 中使用 gulp。 但是后來我看了 webpack 可以代替 gulp 嗎? 我在這里完全糊塗了……有人可以解釋一下嗎?

更新

最后我從 gulp 開始。 我是現代前端的新手,只想快速啟動和運行。 一年多后,我的腳已經濕透了,我准備轉向 webpack。 對於穿着相同鞋子的人,我建議采用相同的路線。 不是說你不能嘗試 webpack,而是說如果它看起來很復雜,首先從 gulp 開始......沒有錯。

如果您不想要 gulp,是的,有 grunt,但您也可以只在 package.json 中指定命令並從命令行調用它們,而無需任務運行器,只是為了最初啟動和運行。 例如:

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

這個答案可能會有所幫助。 任務運行器(Gulp、Grunt 等)和捆綁器(Webpack、Browserify)。 為什么一起用?

...這是在 gulp 任務中使用 webpack 的示例。 這更進一步,假設您的 webpack 配置是用 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();
            }
        }
    }
}

我想您會發現隨着您的應用程序變得越來越復雜,您可能希望按照上面的示例將 gulp 與 webpack 任務一起使用。 這允許您在構建中做一些 webpack 加載器和插件真正不做的更有趣的事情,即。 創建輸出目錄,啟動服務器等。簡而言之,webpack 實際上可以做這些事情,但你可能會發現它們對於你的長期需求是有限的。 您從 gulp -> webpack 獲得的最大優勢之一是您可以針對不同的環境自定義您的 webpack 配置,並讓 gulp 在正確的時間執行正確的任務。 這真的取決於你,但是從 gulp 運行 webpack 並沒有錯,事實上有一些非常有趣的例子來說明如何做到這一點。 上面的例子基本上來自jlong​​ster

NPM 腳本可以執行與 gulp 相同的功能,但代碼減少了大約 50 倍。 事實上,根本沒有代碼,只有命令行參數。

例如,您描述的用例中,您希望為不同的環境使用不同的代碼。

使用 Webpack + NPM 腳本,就這么簡單:

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

現在您只需維護兩個 webpack 配置腳本,一個用於開發模式webpack.development.js ,另一個用於生產模式webpack.production.js 我還使用了一個webpack.common.js ,它包含在所有環境中共享的 webpack 配置,並使用 webpackMerge 來合並它們。

由於 NPM 腳本的酷炫,它允許輕松鏈接,類似於 gulp 處理 Streams/pipes 的方式。

在上面的示例中,要為開發而構建,您只需轉到命令行並執行npm run build:dev

  1. NPM 將首先運行prebuild:dev
  2. 然后build:dev
  3. 最后是postbuild:dev

prepost前綴告訴 NPM 以哪個順序執行。

如果您注意到,使用 Webpack + NPM 腳本,您可以運行本機程序,例如rimraf ,而不是運行本機程序(例如rimraf gulp-rimraf 您還可以像我在這里使用elevate.exe或 Linux 或 Mac 上的本機 *nix 文件一樣運行本機 Windows .exe 文件。

嘗試用 gulp 做同樣的事情。 您將不得不等待有人來為您要使用的本機程序編寫一個 gulp-wrapper。 此外,您可能需要像這樣編寫復雜的代碼:(直接取自angular2-seed repo)

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 生產代碼

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

實際的 gulp 代碼比這復雜得多,因為這只是 repo 中幾十個 gulp 文件中的 2 個。

那么,哪一個對你來說更容易呢?

在我看來,NPM 腳本在有效性和易用性方面都遠遠超過了 gulp 和 grunt,所有前端開發人員都應該考慮在他們的工作流程中使用它,因為它可以節省大量時間。

更新

我遇到過一種情況,我想將 Gulp 與 NPM 腳本和 Webpack 結合使用。

例如,當我需要在 iPad 或 Android 設備上進行遠程調試時,我需要啟動額外的服務器。 過去,我在 IntelliJ IDEA(或 Webstorm)中將所有服務器作為單獨的進程運行,這很容易使用“復合”運行配置。 但是,如果我需要停止並重新啟動它們,則必須關閉 5 個不同的服務器選項卡很乏味,而且輸出分布在不同的窗口中。

gulp 的好處之一是可以將來自不同獨立進程的所有輸出鏈接到一個控制台窗口中,該窗口成為所有子服務器的父級。

所以我創建了一個非常簡單的 gulp 任務,它直接運行我的 NPM 腳本或命令,所以所有輸出都出現在一個窗口中,我可以通過關閉 gulp 任務窗口輕松地一次結束所有 5 個服務器。

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

在我看來,仍然有相當多的代碼只是為了運行 5 個任務,但它可以達到目的。 一個警告是gulp-shell似乎沒有正確運行某些命令,例如ios-webkit-debug-proxy 所以我不得不創建一個 NPM 腳本來執行相同的命令,然后它就可以工作了。

所以我主要使用 NPM 腳本來完成我的所有任務,但偶爾當我需要同時運行一堆服務器時,我會啟動我的 Gulp 任務來提供幫助。 為正確的工作選擇正確的工具。

更新 2

我現在使用一個名為concurrently的腳本,它與上面的 gulp 任務做同樣的事情。 它並行運行多個 CLI 腳本並將它們全部通過管道傳送到同一個控制台窗口,並且使用起來非常簡單。 再一次,不需要代碼(好吧,代碼在 node_module 中並發,但您不必擔心)

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

這將並行運行所有 5 個腳本,並通過管道輸出到一個終端。 驚人的! 所以這一點,我很少使用 gulp,因為有很多 cli 腳本可以在沒有代碼的情況下完成相同的任務。

我建議你閱讀這些文章,對它們進行深入比較。

我在不同的項目中使用了這兩個選項。

這里是一個樣板,我放在一起用gulpwebpack - https://github.com/iroy2000/react-reflux-boilerplate-with-webpack

我有一些其他項目只使用webpacknpm tasks

他們都工作得很好。 我認為它歸結為您的任務有多復雜,以及您希望在配置中擁有多少控制權。

例如,如果您的任務很簡單,比如說devbuildtest ……等等(這是非常標准的),那么您只需webpack帶有npm tasks簡單webpack就完全webpack了。

但是,如果您的工作流程非常復雜,並且希望對配置有更多的控制權(因為它是編碼),則可以選擇 gulp 路線。

但是根據我的經驗,webpack 生態系統提供了足夠多的插件和加載器,我需要,所以我喜歡使用最低限度的方法,除非有些事情你只能在 gulp 中完成。 而且,如果您的系統中少一件東西,它會使您的配置更容易。

很多時候,現在,我看到人們實際上單獨用webpack代替了gulp and browsifywebpack

Gulp 和 Webpack 的概念完全不同。 你告訴 Gulp如何一步一步地把前端代碼放在一起,但是你通過一個配置文件告訴 Webpack 你想要什么

這是我寫的一篇短文(閱讀 5 分鍾),解釋了我對差異的理解: https : //medium.com/@Maokai/compile-the-front-end-from-gulp-to-webpack-c45671ad87fe

我們公司在去年從 Gulp 遷移到了 Webpack。 雖然花費了一些時間,但我們想出了如何將我們在 Gulp 中所做的一切遷移到 Webpack。 所以對我們來說,我們在 Gulp 中所做的一切都可以通過 Webpack 來完成,但反過來不行。

到今天為止,我建議只使用 Webpack,避免將 Gulp 和 Webpack 混合使用,這樣您和您的團隊就不需要學習和維護兩者,尤其是因為它們需要非常不同的思維方式。

老實說,我認為最好是同時使用兩者。

  • 用於所有javascript相關的Webpack
  • 吞咽所有與css相關的內容。

我仍然需要找到一個像樣的解決方案來使用 webpack 打包 css,到目前為止我很高興使用 gulp 來處理 css 和 webpack 來處理 javascript。

我還使用npm腳本作為 @Tetradev 所述。 Expecially因為我使用Visual Studio ,並同時NPM Task runner是相當可靠Webpack Task Runner是相當馬車

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM