const gulp = require('gulp');
gulp.task('default', function() {
gulp.src('js/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
複製代碼
注意:默認的,task 將以最大的併發數執行,gulp 會一次性運行全部的 task 而且不作任何等待。若是你想要建立一個序列化的 task 隊列,並以特定的順序執行,你須要作兩件事:node
var gulp = require('gulp');
// 返回一個 callback,所以系統能夠知道它何時完成
gulp.task('one', function(cb) {
// 作一些事 -- 異步的或者其餘的
cb(err); // 若是 err 不是 null 或 undefined,則會中止執行,且注意,這樣表明執行失敗了
這裏也可使用 return 代替 cb()
});
// 定義一個所依賴的 task 必須在這個 task 執行以前完成
gulp.task('two', ['one'], function() {
// 'one' 完成後
});
gulp.task('default', ['one', 'two']);
複製代碼
我的認爲了解 gulp 的核心知識,主要從三個方面來了解:git
上面三點分別對應了gulp的 pipe(這樣寫不太嚴謹,由於pipe是流的api),src和task 這三個API,瞭解了這三部分,gulp的使用,插件的編寫都會比較駕輕就熟。github
說實話到如今也沒有對流的全部知識十分了解,以前查閱了一些 node 相關的書,感受不少書寫的東西和例子都很淺,後來看了一些文章,算是瞭解了一點皮毛。這是網傳的學習流必看的文章,有興趣的能夠看看。gulp
本文默認讀者對流有了必定的瞭解,所以這裏對流的種類,相關API和使用不會說的很詳細。併發
stream不會佔用大量內存。例如 fs.readFile 在讀取文件時,會把整個文件讀取到內存當中,當文件很大時,會很佔用內存,甚至會超出v8的內存限制,致使程序退出。流則是讀一部分,寫一部分,並且可以充分地利用 Buffer 不受 V8 內存控制的特色,利用堆外內存完成高效地傳輸。異步
gulp 內部使用了 through2 封裝好的 transform 流(後面會展開說),這一步是在 gulp.src 的時候完成的,所以咱們能夠看到這樣的代碼:函數
gulp.src(xxx).pipe(xxx)...
複製代碼
我我的理解的 pipe 就是一根水管,左邊是可讀流(readStream),右邊是可寫流(writeStream)。正由於 gulp 幫咱們封裝好了流,所以,咱們能夠直接使用 pipe 這個 api 來傳輸數據。oop
學習插件的編寫能讓咱們對gulp中流的使用有更深刻的認識,有的時候可能咱們須要一些定製話的功能來處理文件,這時就須要本身編寫gulp的插件了,咱們先來看一個官方的例子:學習
var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
// 常量
const PLUGIN_NAME = 'gulp-prefixer';
function prefixStream(prefixText) {
var stream = through();
stream.write(prefixText);
return stream;
}
// 插件級別函數 (處理文件)
function gulpPrefixer(prefixText) {
if (!prefixText) {
throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
}
prefixText = new Buffer(prefixText); // 預先分配
// 建立一個讓每一個文件經過的 stream 通道
return through.obj(function(file, enc, cb) {
if (file.isNull()) {
// 返回空文件
cb(null, file);
}
if (file.isBuffer()) {
file.contents = Buffer.concat([prefixText, file.contents]);
}
if (file.isStream()) {
file.contents = file.contents.pipe(prefixStream(prefixText));
}
cb(null, file);
});
};
// 暴露(export)插件主函數
module.exports = gulpPrefixer;
複製代碼
對於 gulp 插件的編寫我認爲這兩點是比較重要的:
帶着這些疑問,咱們先看下 through2 的源碼:源碼地址
// 前面的代碼建立了一個 Transform 流,並給這個流添加了一個 destroy 方法
function through2 (construct) {
return function (options, transform, flush) {
if (typeof options == 'function') {
flush = transform
transform = options
options = {}
}
if (typeof transform != 'function')
transform = noop
if (typeof flush != 'function')
flush = null
return construct(options, transform, flush)
}
}
module.exports.obj = through2(function (options, transform, flush) {
var t2 = new DestroyableTransform(Object.assign({ objectMode: true, highWaterMark: 16 }, options))
t2._transform = transform
if (flush)
t2._flush = flush
return t2
})
複製代碼
文件系統這個名字說着有點懸乎,其實這部分就是介紹一下 gulp.src 是怎麼把文件加工成流的。
未完待續。。。