首页 文章

Gulp Webpack还是JUST Webpack?

提问于
浏览
138

我看到人们使用gulp和webpack . 但后来我看了webpack可以取代gulp?我在这里完全糊涂了......有人可以解释一下吗?

UPDATE

最后我开始喝了一口气 . 我是现代前端的新手,只是想快速起步和跑步 . 现在,经过一年多的时间,我的脚已经湿透了,我已准备好转向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"
    },

5 回答

  • 71

    这个答案可能有帮助 . Task Runners (Gulp, Grunt, etc) and Bundlers (Webpack, Browserify). Why use together?

    ...这里是一个在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();
                }
            }
        }
    }
    

    我认为你这样做,即 . 创建输出目录,启动服务器等等 . 嗯,简洁,webpack实际上可以做这些事情,但你可能会发现它们仅限于你的长期需求 . 从gulp - > webpack获得的最大优势之一是,您可以针对不同的环境自定义webpack配置,并让gulp在正确的时间执行正确的任务 . 它真的取决于你,但有一些很好的例子,如何做到这一点 . 上面的例子基本上来自jlongster .

  • 2

    NPM scripts 可以和gulp一样,但代码减少约50倍 . 实际上,根本没有代码,只有命令行参数 .

    例如,您描述的用例,您希望在不同环境中使用不同的代码 .

    With Webpack + NPM Scripts, it's this easy:

    "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 config,并使用webpackMerge合并它们 .

    由于NPM脚本的酷感,它允许轻松链接,类似于吞咽/管道的吞咽方式 .

    在上面的示例中,要构建开发,只需转到命令行并执行 npm run build:dev .

    • NPM将首先运行 prebuild:dev

    • 然后 build:dev

    • 最后 postbuild:dev .

    prepost 前缀告诉NPM要执行的命令 .

    如果您注意到,使用Webpack NPM脚本,您可以运行本机程序,例如 rimraf ,而不是本机程序(例如 gulp-rimraf )的gulp-wrapper . 您也可以像在Linux或Mac上使用 elevate.exe 或native * nix文件一样运行本机Windows .exe文件 .

    尝试用gulp做同样的事情 . 你'll have to wait for someone to come along and write a gulp-wrapper for the native program you want to use. In addition, you'可能需要编写这样的复杂代码:(直接从angular2-seed repo获取)

    Gulp Development code

    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 Production code

    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文件中的两个 .

    那么,哪一个更容易?

    在我看来,NPM脚本在效率和易用性方面远远超过了gulp和grunt,并且所有前端开发人员都应该考虑在他们的工作流程中使用它,因为它节省了大量时间 .

    UPDATE

    我遇到过一个场景,我想将Gulp与NPM脚本和Webpack结合使用 .

    例如,当我需要在iPad或Android设备上进行远程调试时,我需要启动额外的服务器 . 在过去,我将所有服务器作为单独的进程运行,从IntelliJ IDEA(或Webstorm)中运行,这很容易通过"Compound"运行配置 . 但是,如果我需要停止并重新启动它们,必须关闭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任务来帮忙 . 为正确的工作选择合适的工具 .

    UPDATE 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脚本可以执行相同的任务而没有代码 .

    I suggest you read these articles which compare them in depth.

  • 72

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

    这是我使用 gulpwebpack - https://github.com/iroy2000/react-reflux-boilerplate-with-webpack组合在一起的一个样板 .

    我有一些其他项目仅使用 webpacknpm tasks .

    他们都完美无缺 . 而且我认为这可以归结为您的任务有多复杂,以及您希望在配置中拥有多少控制权 .

    例如,如果你的任务很简单,那就说 devbuildtest ......等(这是非常标准的),只需简单的 webpacknpm tasks 就可以了 .

    但是如果你有非常复杂的工作流程并且想要更多地控制你的配置(因为它是编码),你可以选择gulp route .

    但根据我的经验,webpack生态系统提供了我需要的足够的插件和加载器,所以我喜欢使用最小的方法,除非你有一些事情只能在gulp中做 . 而且,如果您的系统中少了一些东西,它将使您的配置更容易 .

    很多时候,如今,我看到人们实际上只用 webpack 替换 gulp and browsify .

  • 8

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

    • Webpack 为所有 javascript 相关 .

    • Gulp 为所有 css 相关 .

    我仍然需要找到一个适合用webpack打包css的解决方案,到目前为止,我很高兴使用gulp for css和webpack for javascript .

    我也使用 npm 脚本作为@Tetradev描述 . 特别是因为我正在使用 Visual Studio ,而 NPM Task runner 很漂亮 reliable Webpack Task Runner 很漂亮 buggy .

  • 0

    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,这样你和你的团队就不需要学习和维护两者,特别是因为他们需要非常不同的思维模式 .

相关问题