的 NPM脚本 强> 可以像gulp一样,但代码减少约50倍。实际上,根本没有代码,只有命令行参数。
例如,您描述的用例,您希望在不同环境中使用不同的代码。
的 使用Webpack + NPM Scripts,就是这么简单: 强>
"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来合并它们。
webpack.development.js
webpack.production.js
webpack.common.js
由于NPM脚本很酷,它允许轻松链接,类似于吞咽/管道吞咽的方式。
在上面的示例中,要构建开发,只需转到命令行并执行即可 npm run build:dev 。
npm run build:dev
prebuild:dev
build:dev
postbuild:dev
该 pre 和 post 前缀告诉NPM要执行的命令。
pre
post
如果您注意到,使用Webpack + NPM脚本,您可以运行本机程序,例如 rimraf 而不是像本机程序的gulp-wrapper gulp-rimraf 。您也可以像我在这里一样运行本机Windows .exe文件 elevate.exe 或Linux或Mac上的本机* nix文件。
rimraf
gulp-rimraf
elevate.exe
尝试用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代码要复杂得多,因为这只是repo中几十个gulp文件中的两个。
那么,哪一个更容易?
在我看来,NPM脚本在效率和易用性方面远远超过gulp和grunt,并且所有前端开发人员都应该考虑在他们的工作流程中使用它,因为它节省了大量时间。
的 UPDATE 强>
我遇到过一个场景,我想将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脚本,然后它才能工作。
gulp-shell
ios-webkit-debug-proxy
所以我主要使用NPM脚本完成我的所有任务,但偶尔当我需要同时运行一堆服务器时,我会启动我的Gulp任务来帮忙。为正确的工作选择合适的工具。
的 更新2 强>
我现在使用一个名为的脚本 同时 这与上面的gulp任务完全相同。它并行运行多个CLI脚本,并将它们全部管道到同一个控制台窗口,并且使用起来非常简单。再一次,不需要代码(嗯,代码在node_module中同时进行,但你不必担心自己) p>
// 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脚本可以执行相同的任务而无需代码。
的 我建议你阅读这些文章,深入比较它们。 强>
这个答案可能有帮助。 任务运行者(Gulp,Grunt等)和Bundlers(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获得的最大优势之一 - &gt; webpack是您可以为不同的环境自定义webpack配置,并让gulp在正确的时间执行正确的任务。它真的取决于你,但是从gulp运行webpack并没有什么问题,事实上它有点漂亮 有趣 如何做的例子。上面的例子基本上来自 jlongster 。
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,这样你和你的团队就不需要学习和维护两者,特别是因为他们需要非常不同的思维模式。
老实说,我认为最好是同时使用两者。
我仍然需要找到一个适合用webpack打包css的解决方案,到目前为止,我很高兴使用gulp用于css和webpack for javascript。
我也用 npm 如上所述,脚本为@Tetradev。特别是因为我正在使用 Visual Studio ,同时 NPM Task runner 很漂亮 的 可靠 强> Webpack Task Runner 很漂亮 的 越野车 强> 。
npm
Visual Studio
NPM Task runner
Webpack Task Runner
我在不同的项目中使用了这两个选项。
这是我使用的一个样板 gulp 同 webpack - https://github.com/iroy2000/react-reflux-boilerplate-with-webpack 。
gulp
webpack
我还有其他一些项目 webpack 同 npm tasks 。
npm tasks
他们都完美无缺。而且我认为这可以归结为您的任务有多复杂,以及您希望在配置中拥有多少控制权。
例如,如果你的任务很简单,那就说吧 dev , build , test ...等(这是非常标准的),只需简单就完全没问题了 webpack 同 npm tasks 。
dev
build
test
但是如果你有非常复杂的工作流程并且你想要更多地控制你的配置(因为它是编码),你可以选择gulp route。
但根据我的经验,webpack生态系统提供了我需要的足够的插件和加载器,所以我喜欢使用最小的方法,除非你只能做一些事情。而且,如果您的系统中少了一些东西,它将使您的配置更容易。
很多时候,如今,我看到人们实际上正在取代 gulp and browsify 一起来 webpack 单独。
gulp and browsify