Các tập lệnh NPM có thể làm tương tự như gulp, nhưng trong mã ít hơn khoảng 50 lần. Trong thực tế, không có mã nào cả, chỉ có các đối số dòng lệnh.
Ví dụ: trường hợp sử dụng mà bạn mô tả nơi bạn muốn có mã khác nhau cho các môi trường khác nhau.
Với Webpack + NPM ScScript, thật dễ dàng:
"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/*\"",
Bây giờ bạn chỉ cần duy trì hai tập lệnh cấu hình webpack, một cho chế độ phát triển webpack.development.js
và một cho chế độ sản xuất , webpack.production.js
. Tôi cũng sử dụng webpack.common.js
cấu hình webpack được chia sẻ trên tất cả các môi trường và sử dụng webpackMerge để hợp nhất chúng.
Do tính mát mẻ của các tập lệnh NPM, nó cho phép dễ dàng xâu chuỗi, tương tự như cách gulp thực hiện Streams / pipe.
Trong ví dụ trên, để xây dựng để phát triển, bạn chỉ cần vào dòng lệnh của mình và thực thi npm run build:dev
.
- NPM đầu tiên sẽ chạy
prebuild:dev
,
- Sau đó
build:dev
,
- Và cuối cùng
postbuild:dev
.
Các tiền tố pre
và post
tiền tố cho NPM biết thứ tự thực hiện.
Nếu bạn nhận thấy, với các tập lệnh Webpack + NPM, bạn có thể chạy một chương trình gốc, chẳng hạn như rimraf
, thay vì một trình bao bọc cho một chương trình gốc, chẳng hạn như gulp-rimraf
. Bạn cũng có thể chạy các tệp .exe của Windows như tôi đã làm ở đây với elevate.exe
hoặc các tệp * nix gốc trên Linux hoặc Mac.
Hãy thử làm điều tương tự với gulp. Bạn sẽ phải đợi ai đó đi cùng và viết một gói bọc cho chương trình gốc mà bạn muốn sử dụng. Ngoài ra, bạn có thể sẽ cần phải viết mã phức tạp như thế này: (lấy trực tiếp từ repo angular2-seed )
Mã phát triển 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));
};
Mã sản xuất 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));
};
Mã gulp thực tế phức tạp hơn nhiều, vì đây chỉ là 2 trong số vài chục tệp gulp trong repo.
Vì vậy, cái nào là dễ dàng hơn với bạn?
Theo tôi, các kịch bản NPM vượt xa gulp và grunt, cả về tính hiệu quả và dễ sử dụng, và tất cả các nhà phát triển front-end nên xem xét sử dụng nó trong quy trình làm việc của họ vì đây là một trình tiết kiệm thời gian chính.
CẬP NHẬT
Có một kịch bản tôi đã gặp phải khi tôi muốn sử dụng Gulp kết hợp với các tập lệnh NPM và Webpack.
Khi tôi cần gỡ lỗi từ xa trên thiết bị iPad hoặc Android chẳng hạn, tôi cần khởi động thêm máy chủ. Trước đây, tôi đã chạy tất cả các máy chủ dưới dạng các quy trình riêng biệt, từ bên trong IntelliJ IDEA (Hoặc Webstorm) rất dễ dàng với Cấu hình chạy "Hợp chất". Nhưng nếu tôi cần dừng và khởi động lại chúng, thật tẻ nhạt khi phải đóng 5 tab máy chủ khác nhau, cộng với đầu ra được trải đều trên các cửa sổ khác nhau.
Một trong những lợi ích của gulp là có thể xâu chuỗi tất cả đầu ra từ các quy trình độc lập riêng biệt vào một cửa sổ giao diện điều khiển, trở thành cha mẹ của tất cả các máy chủ con.
Vì vậy, tôi đã tạo một tác vụ gulp rất đơn giản, chỉ chạy trực tiếp các tập lệnh NPM hoặc các lệnh, vì vậy tất cả đầu ra xuất hiện trong một cửa sổ và tôi có thể dễ dàng kết thúc tất cả 5 máy chủ cùng một lúc bằng cách đóng cửa sổ tác vụ gulp.
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'));
Theo tôi, vẫn còn khá nhiều mã chỉ để chạy 5 tác vụ, nhưng nó hoạt động đúng với mục đích. Một điều lưu ý là gulp-shell
dường như không chạy một số lệnh chính xác, chẳng hạn như ios-webkit-debug-proxy
. Vì vậy, tôi đã phải tạo một NPM Script chỉ thực hiện cùng một lệnh và sau đó nó hoạt động.
Vì vậy, tôi chủ yếu sử dụng Tập lệnh NPM cho tất cả các nhiệm vụ của mình, nhưng thỉnh thoảng khi tôi cần chạy một loạt các máy chủ cùng một lúc, tôi sẽ kích hoạt nhiệm vụ Gulp của mình để giúp đỡ. Chọn công cụ phù hợp cho công việc phù hợp.
CẬP NHẬT 2
Bây giờ tôi sử dụng một tập lệnh được gọi đồng thời , thực hiện tương tự như nhiệm vụ gulp ở trên. Nó chạy song song nhiều tập lệnh CLI và chuyển tất cả chúng vào cùng một cửa sổ giao diện điều khiển và rất đơn giản để sử dụng. Một lần nữa, không yêu cầu mã (tốt, mã nằm trong nút_module đồng thời, nhưng bạn không phải lo lắng về điều đó)
// 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"
Điều này chạy tất cả 5 tập lệnh song song được dẫn đến một thiết bị đầu cuối. Tuyệt vời! Vì vậy, điểm này, tôi hiếm khi sử dụng gulp, vì có rất nhiều tập lệnh cli để thực hiện các nhiệm vụ tương tự mà không có mã.
Tôi đề nghị bạn đọc những bài viết này so sánh chúng sâu sắc.