Gulp + Webpack还是Just Webpack?


161

我看到人们在Webpack中使用gulp。但是后来我看webpack可以代替gulp吗?我在这里完全困惑...有人可以解释吗?

更新

最后,我从吞咽开始。我刚接触现代前端,只是想快速起步并运行。一年多以后,现在我的脚已经湿透了,现在可以开始使用webpack了。对于那些穿着相同鞋子的人,我建议使用相同的路线。并不是说您不能尝试使用webpack,而是先说一下是否看起来很复杂,首先从gulp开始...这没错。

如果您不希望吞咽,是的,虽然有些麻烦,但是您也可以在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"
    },

3
这比Webpack自己的文档或任何文章帮助我更好地掌握了Webpack:github.com/petehunt/webpack-howto
George Ananda Eman

blog.andrewray.me/webpack-何时使用以及为什么不需要在Webpack中使用gulp
Andy Ray

我简单而简单的示例是,我希望webpack-dev-server使用HMR处理我的js,但遇到了无法使用静态站点生成器和webpack dev服务器的问题。使用复杂的配置,我可以实现这一目标,但是直截了当,我也可以做到。所以主要的区别是时间和学习曲线。
dewwwald

2年后,我仍然在类似问题上奋斗 ……
Frank Nocke

您的更新应该是一个答案,+1
Z. Khullah

Answers:


82

这个答案可能会有所帮助。 任务运行器(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并没有错,实际上,有一些非常有趣的示例。


我的webpack项目很大-因此我还需要通过命令行命令stackoverflow.com/questions/34727743/…来增加节点内存。有什么方法可以直接通过webpack这样做吗?
Abhinav Singi '16

检查这两个。您可能必须在运行节点或Webpack之前设置v8内存。 stackoverflow.com/questions/7193959/…webpack.github.io/docs/build-performance.html
4m1r

我不确定为什么我接受这个答案。我想这可能是由于您共享的第一个链接。但是使用来自gulp的webpack吗?如果您现在问我,那将更是一团糟:)。我什至不会尝试诉诸类似的东西。
PositiveGuy

80

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,而不是诸如的本机程序的gulp -wrapper gulp-rimraf。您也可以像在此一样运行本机Windows .exe文件,elevate.exe或者在Linux或Mac上运行本机* nix文件。

尝试用gulp做同样的事情。您将不得不等待有人来为您要使用的本机程序编写gulp-wrapper。另外,您可能需要编写如下复杂的代码:(直接从angular2种子回购中获取)

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代码要复杂得多,因为这只是回购中数十个gulp文件中的2个。

那么,哪个更容易?

在我看来,NPM脚本在有效性和易用性方面都远远超过了吞吞吐吐的烦恼,并且所有前端开发人员都应考虑在工作流程中使用它,因为它可以节省大量时间。

更新

我遇到一种情况,我想结合使用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

现在,我使用并发调用的脚本,该脚本的功能与上述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脚本无需代码即可完成相同的任务。

我建议您阅读这些文章,对它们进行深入比较。


14
这是因为您的任务相对容易。祝您好运,并使用Shell构建复杂的脚本:-)
Filip Sobczak

5
这些仅是示例。我的构建非常复杂,并且在shell上执行了许多脚本,可以完美地工作并且易于维护。而且,NPM脚本对我不起作用,而webpack对我不起作用,例如uglify,压缩gzip,变换等。谢谢。有什么复杂的事情需要您大吃一惊?
2016年

2
(一年多以后大声笑):非常感谢,出色的答复!!
PositiveGuy

1
@ user108471当然,webpack可以创建一个assets.json,其中列出了使用相关ID编译的所有模块。可以使用合适的插件创建更多类型的构建时信息JSON文件。您指的是这种吞食可以做什么?
TetraDev

1
@GiannosCharalambous感谢您的提示。我实际上已经使用npm-run-all了几个月,但是我什至没有想到要使用-pparallel标志!我将在本周尝试一下
TetraDev

8

我在不同的项目中都使用了这两个选项。

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

我只有用一些其他的项目webpacknpm tasks

他们俩都工作得很好。我认为这归结为您的任务有多复杂,以及您希望在配置中拥有多少控制权。

例如,如果你的任务很简单,让我们说devbuildtest...等(这是非常标准的),你是完全罚款只是简单的webpacknpm tasks

但是,如果您的工作流程非常复杂,并且希望对配置进行更多控制(因为它是在编码),则可以采用gulp路由。

但是根据我的经验,webpack生态系统提供了我所需的足够多的插件和加载器,因此,我喜欢使用最低限度的方法,除非有些事情只能在gulp中完成。而且,如果您的系统中少了一件东西,它将使您的配置更加容易。

如今,很多时候,我看到人们实际上将gulp and browsify所有的人都替换成了一个人webpack


5
是的,但是Webpack在理解上过于复杂而臭名昭著。我倾向于尝试先在浏览器中使用gulp,但尚未准备好使用Webpack,部分原因是我对前端的Browserify或node并没有做很多事情,所以我想了解每个人如何使用gulp和browserify第一只是让我有一个历史的经验而言
PositiveGuy

1
Webpack只有在您不使用它的情况下才变得复杂,就像gulp,grunt,browserify,打字稿等。一旦了解了如何设置配置文件以及如何使用加载程序,Webpack便非常易于使用。实际上,对于一个有效的Webpack构建来说,配置文件可以短到20至30行代码,并且可以根据需要而强大。更不用说Webpack热模块更换绝对是惊人的。请参阅:andrewhfarmer.com/understanding-hmrandrewhfarmer.com/webpack-hmr-tutorial and medium.com/@dabit3/beginner-s-guide-to-webpack-b1f1a3638460
TetraDev

2

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混用,这样您和您的团队就无需学习和维护两者,尤其是因为它们需要非常不同的思维方式。


2

老实说,我认为最好是同时使用两者。

  • 所有与javascript相关的Webpack
  • 与所有CSS相关的Gulp

我仍然必须找到一种用webpack打包css的不错的解决方案,到目前为止,我很高兴将gulp用于css和将webpack用于javascript。

npm如上所述,我也将脚本用作@Tetradev。特别是因为我正在使用Visual Studio,并且虽然NPM Task runner可靠 Webpack Task Runner,但是却很容易出错


我发现使用NPM Task Runner + Gulp是关键。将webpack命令放入packange.json文件中,并将相关的CSS(SASS)放入gulp文件中。还要将package.json设置为具有生成步骤,该步骤将gulp任务作为生产版本的一部分进行调用
Nico
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.