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
。
- NPM将首先运行
prebuild:dev
,
- 然后
build:dev
,
- 最后
postbuild:dev
。
在pre
和post
前缀告诉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脚本无需代码即可完成相同的任务。
我建议您阅读这些文章,对它们进行深入比较。