簡單說來尝艘,gulp的api非常簡單。只有4個锣险,他們分別是gulp.src
gulp.dest
gulp.task
gulp.watch
因此旬昭,想要簡單的使用gulp很容易篙螟,但是想要將gulp使用到得心應(yīng)手的地步并不是一件簡單的事情。 而其中最關(guān)鍵的地方在于问拘,對nodejs文件路徑匹配模式globs的理解遍略。
gulp的4個api中:
- gulp.task創(chuàng)建一個任務(wù)
- gulp.src表示創(chuàng)建的任務(wù)是針對文件目錄中的那些位置
- gulp.dest表示目標文件被處理完畢之后會在哪個位置重新生成
- gulp.watch表示監(jiān)聽那些位置文件的變化
除了task,其他三個api都與文件路徑密切相關(guān)骤坐,而gulp.src與gulp.watch更是直接以golbs為第一個參數(shù)绪杏, gulp的各個插件需要知道自己處理的是那些位置的文件,而golbs則負責(zé)指定需要被處理文件的位置
每個人對前端的理解有所差異或油,造成了前端的項目結(jié)構(gòu)也是各不一樣寞忿,因此golbs的配置也就顯得更加重要 下面就一起來了解一下驰唬,golbs的匹配規(guī)則顶岸。
粗略讀一遍可能并不能掌握腔彰,所以建議大家收藏起來,留著以后慢慢看
匹配文件中0個或者多個字符辖佣,但是不會匹配路徑中的分隔符霹抛,除非路徑分隔符出現(xiàn)在末尾 例如下面的寫法
// 匹配./style目錄下所有的js文件
./style/*.js
// 匹配./style目錄下所有的文件
./style/*.*
// 只要層級相同,可以匹配任意目錄下的任意js文件 比如./style/a/b.js
./style/*/*.js
匹配文件路徑中的0個或者多個層級的目錄卷谈,需要單獨出現(xiàn)杯拐,如果出現(xiàn)在末尾,也可匹配文件
// 匹配style目錄及其所有子目錄下的所有js文件世蔗,如能匹配
// ./style/a.js
// ./style/lib/res.js
// ./style/mudules/b/a.js
./style/**/*.js
// 匹配style目錄下的所有目錄和文件端逼,比如能匹配
// ./style/a.js
// ./style/bb
// ./style/images/c.png
./style/**/*
//? 匹配一個字符,不會匹配路徑分隔符
// 能匹配文件名只有一個字符的js文件污淋,如a.js, b.js ,但不能匹配文件名為2個字符及其以上的js的文件
?.js
[...] 由多個規(guī)則組成的數(shù)組顶滩,可以匹配數(shù)組中符合任意一個子項的文件,當(dāng)子項中第一個字符為!或者^時寸爆,表示不匹配該規(guī)則
// 匹配style目錄下的a0.js, a1.js, a2.js, a3.js
'./style/a[0-3].js'
// 除開node_modules目錄之外礁鲁,匹配項目根目錄下的所有html文件
['./**/*.html', '!node_modules/**']
{...} 展開模式,根據(jù)里面的內(nèi)容展開為多個規(guī)則赁豆,能匹配所有展開之后的規(guī)則 將上面的例子擴展一下仅醇,可以如下寫
// 除開build,simple,images,node_modules目錄,匹配根目錄下所有的html與php文件
['./**/*.{html, php}', '!{build, simple, images, node_modules}/**']
!(pattern|pattern|pattern) 每一個規(guī)則用pattern表示魔种,這里指排除符合這幾個模式的所有文件
// 匹配排除文件名為一個字符的js文件析二,以及排除jquery.js之后的所有js文件
'./style/!(?|jquery).js'
// 排除build與node_modules目錄,并排除其他目錄下以下劃線_開頭的html與php文件务嫡,匹配其余的html與php文件
// 這種比較復(fù)雜的規(guī)則在實際開發(fā)中會常常用到甲抖,需要加深了解
['./**/!(_)*.{html, php}', '!{build, node_modules}/**']
?(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或者1次
// 匹配style目錄下的a.js, a2.js, b.js
// 不能組合
// 匹配0次或者1次
'./style/?(a|a2|b).js'
@(pattern|pattern|pattern) 匹配多個模式中的任一個
// 匹配style目錄下的a.js, b.js, c.js
// 不能組合
// 匹配一次,不能為空心铃,注意與?的區(qū)別
'./style/@(a|b|c).js'
+(pattern|pattern|pattern) 匹配括號中給定任一模式1次或者多次准谚,這幾個模式可以組合在一起匹配
// 可以匹配style目錄下的a.js, a2.js, b.js
// 也可以匹配他們的組合 ab.js, aa2.js, a2b.js等
// 至少匹配一次,為空不匹配
'./style/+(a|a2|b).js'
(pattern|pattern|pattern) 匹配括號中給定任一模式0次或者多次去扣,這幾個模式可以組合在一起匹配
// 可以匹配style目錄下的a.js, b.js, c.js
// 也可以匹配他們的組合 ab.js, bc.js, ac.js
// 匹配0次或者多次
'./style/*(a|b|c).js'
幾乎能用到的規(guī)則就都在上面了柱衔,在實際使用的時候,我們需要根據(jù)自己的實際情況來使用 只要掌握了globs模式愉棱,距離精通gulp也不太遠了唆铐。
API
gulp.src(globs[, options])
徹底了解了globs,那么回過頭來學(xué)習(xí)gulp的這幾個api就變得非常簡單奔滑。 gulp.src指定gulp任務(wù)的目標文件位置 它的參數(shù)中艾岂,第一個參數(shù)globs為必選,中括號表示可選參數(shù)朋其,options為一個配置json對象 globs用于指定目標文件的位置王浴,在上面已經(jīng)做過史上最詳細的介紹脆炎,這里對option做一個簡單的介紹即可
gulp.src('./**/!(_).{php, html}', {
buffer: true,
read: true,
base: './'
})
options.buffer
類型: Boolean 默認:true 如果該項被設(shè)置為false,那么將會以stream方式返回file.contents氓辣,而不是文件buffer的形式秒裕。 這在處理一些大文件的時候非常有用。 另外需要注意點是钞啸,gulp插件可能不支持stream
options.read
類型: Boolean 默認: true 如果被設(shè)置為false几蜻,那么file.contents會返回空值(null) 也就是并不會去讀取文件
options.base
類型: String 默認值: 第一個參數(shù)目錄中,glob匹配模式之前的路徑 理解base至關(guān)重要体斩,它將影響到文件處理完畢后梭稚,新文件生成的目錄 我們需要結(jié)合gulp.dest來理解它。
比如在一個路徑為static/scripts/libs的目錄中絮吵,有一個js組件叫做dialog.js
// 匹配static/scripts/libs/dialog.js哨毁,并將base解析成 static/scripts
gulp.src('static/scripts/**/*.js')
.pipe(minify())
// 處理完畢的文件,將會用build替換掉base源武,即為 build/libs/dialog.js
.pipe(gulp.dest('build'));
// 手動設(shè)置base的值
gulp.src('static/scripts/**/*.js', { base: 'static' })
.pipe(minify())
// 使用build替換base扼褪,結(jié)果為 build/scripts/libs/dialog.js
.pipe(gulp.dest('build'));
gulp.dest(path[, options])
能被pipe進來,并且將會寫文件粱栖。會重新輸出所有數(shù)據(jù)话浇。 也就是說會新建處理完畢之后的文件。 我們可以將他pipe到多個文件夾闹究。如果文件夾不存在幔崖,則會自動新建。 關(guān)于使用方法渣淤,可以結(jié)合上面的例子進行理解赏寇。
指定的路徑用于替換gulp.src參數(shù)options中的base,結(jié)果就是新文件的位置
gulp.dest的options沒怎么使用過价认,感覺沒上面用嗅定,就略過了。
gulp.task(name[, deps], fn)
定義個gulp任務(wù)
gulp.task('somename', function() {
// dosomething
})
name
類型:string 任務(wù)的名字用踩,如果你需要在命令行中運行你的某些任務(wù)渠退,那么不要在任務(wù)名字中使用空格
deps
類型: array 一個包含任務(wù)列表的數(shù)組,這些任務(wù)會在你當(dāng)前任務(wù)運行之前完成
gulp.task('mytask', ['array', 'of', 'task', 'names'], function() {
// dosomething
})
請一定要確保你所依賴的任務(wù)列表中的任務(wù)都使用了正確的異步執(zhí)行方式:使用一個 callback脐彩,或者返回一個 promise 或 stream碎乃。
fn
該函數(shù)定義任務(wù)所需要執(zhí)行的一些操作。通常來說惠奸,它會是這樣中形式
gulp.src().pipe(someplugin())
異步任務(wù)支持 如果fn能夠做到以下其中一點梅誓,就可以異步執(zhí)行了
接受一個callback
// 在 shell 中執(zhí)行一個命令
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
// 編譯 Jekyll
exec('jekyll build', function(err) {
if (err) return cb(err); // 返回 error
cb(); // 完成 task
});
});
返回一個stream
gulp.task('somename', function() {
var stream = gulp.src('client/**/*.js')
.pipe(minify())
.pipe(gulp.dest('build'));
return stream;
});
或者返回一個promise
var Q = require('q');
gulp.task('somename', function() {
var deferred = Q.defer();
// 執(zhí)行異步的操作
setTimeout(function() {
deferred.resolve();
}, 1);
return deferred.promise;
});
默認的,task 將以最大的并發(fā)數(shù)執(zhí)行,也就是說梗掰,gulp 會一次性運行所有的 task 并且不做任何等待删豺。如果你想要創(chuàng)建一個序列化的 task 隊列,并以特定的順序執(zhí)行愧怜,你需要做兩件事:1. 給出一個提示,來告知 task 什么時候執(zhí)行完畢 2.并且再給出一個提示妈拌,來告知一個 task 依賴另一個 task 的完成拥坛。
對于這個例子,讓我們先假定你有兩個 task尘分,"one" 和 "two"猜惋,并且你希望它們按照這個順序執(zhí)行:
a 在 "one" 中,你加入一個提示培愁,來告知什么時候它會完成:可以再完成時候返回一個 callback著摔,或者返回一個 promise 或 stream,這樣系統(tǒng)會去等待它完成定续。
b 在 "two" 中谍咆,你需要添加一個提示來告訴系統(tǒng)它需要依賴第一個 task 完成。
因此私股,這個例子的實際代碼將會是這樣:
var gulp = require('gulp');
// 返回一個 callback摹察,因此系統(tǒng)可以知道它什么時候完成
gulp.task('one', function(cb) {
// 做一些事 -- 異步的或者其他的
// 如果 err 不是 null 或 undefined,則會停止執(zhí)行倡鲸,且注意供嚎,這樣代表執(zhí)行失敗了
cb(err);
});
// 定義一個所依賴的 task 必須在這個 task 執(zhí)行之前完成
gulp.task('two', ['one'], function() {
// 'one' 完成后
});
gulp.task('default', ['one', 'two']);
gulp.watch(glob [, options], tasks) 或 gulp.watch(glob [, options, cb])
監(jiān)視文件,并且可以在文件發(fā)生改動時候做一些事情峭状。它總會返回一個 EventEmitter 來發(fā)射(emit) change 事件克滴。
gulp.watch(glob[, options], tasks)
glob與options略過。
tasks 類型: 數(shù)組 需要在文件變動后執(zhí)行的一個或者多個通過 gulp.task() 創(chuàng)建的 task 的名字优床,
var watcher = gulp.watch('js/**/*.js', ['uglify','reload']);
watcher.on('change', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
gulp.watch(glob[, options, cb])
glob與options略過
cb(event) 類型: Function 每次變動需要執(zhí)行的回調(diào)函數(shù)
gulp.watch('js/**/*.js', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
callback 會被傳入一個名為 event 的對象劝赔。這個對象描述了所監(jiān)控到的變動:
event.type 類型: String 發(fā)生變動的行為類型: added, changed, deleted
event.path 類型: String 觸發(fā)該事件的文件路徑
好啦,gulp的api與最關(guān)鍵的globs都介紹完了胆敞,基本上gulp也算是掌握完畢了望忆。 接下來我們要做的事情就是逐步去了解完成各種任務(wù)的插件了。很多插件都比較簡單竿秆, 在npm上都能夠找到使用方法启摄,所以也就沒什么好擔(dān)心的了。
轉(zhuǎn)自http://yangbo5207.github.io/gulp/2016/08/10/new.html