文章出處

前言:之前一直說著做項目的時候要用gulp ,webpack,結果實習后一直用thinkphp之后就不怎么接觸,不會用gulp/webpack,總覺得不是一個合格的前端開發工作者呀!

        最近做畢設用的是nodejs 的express,gulp使用的是nodejs中stream來讀取和操作數據,所以有nodejs的基礎的話,gulp非常容易理解

一,gulp的安裝

首先要確保安裝好了nodejs的環境,然后以全局的方式安裝gulp

npm install -g gulp

全局安裝后,還要在每個要使用gulp的項目中再安裝一次gulp,把目錄切換到安裝的目錄中

npm install gulp

如果想在安裝的時候把gulp寫進項目package.json文件的依賴中,則可以加上--save-dev:

npm install --save-dev gulp

二,gulp的使用

1,首先新建一個gulpfile.js的文件放在項目的目錄中

我們在文件中定義一個默認的任務

1 var gulp = require('gulp');
2 gulp.task('default',function(){
3     console.log('hello world');
4 });

此時我們的目錄結構是這樣子的:

|----gulpfile.js

|----node-modules

|    |----gulp

|----package.json

2,運行gulp

windows下cmd中切換到項目目錄下 

gulp 任務名

如果沒有指定任務名的話,就會執行default默認的任務

三,gulp的API

1,gulp.src()

在Gulp中,使用的是Nodejs中的stream(流),首先獲取到需要的stream,然后可以通過stream的pipe()方法把流導入到你想要的地方,比如Gulp的插件中,經過插件處理后的流又可以繼續導入到其他插件中,當然也可以把流寫入到文件中。所以Gulp是以stream為媒介的,它不需要頻繁的生成臨時文件.

gulp.src()方法是用來獲取流的但要注意這個流里的內容不是原始的文件流,而是一個虛擬文件對象流(Vinyl files),這個虛擬文件對象中存儲著原始文件的路徑、文件名、內容等信息。用這個方法來讀取你需要操作的文件

語法如下:

gulp.src(globs[, options])

globs參數是文件匹配模式(類似正則表達式),用來匹配文件路徑(包括文件名),當然這里也可以直接指定某個具體的文件路徑。當有多個匹配模式時,該參數可以為一個數組。

options為可選參數。通常情況下我們不需要用到。

Gulp用到的glob的匹配規則以及一些文件匹配技巧。

  • * 匹配文件路徑中的0個或多個字符,但不會匹配路徑分隔符,除非路徑分隔符出現在末尾
  • ** 匹配路徑中的0個或多個目錄及其子目錄,需要單獨出現,即它左右不能有其他東西了。如果出現在末尾,也能匹配文件。
  • ? 匹配文件路徑中的一個字符(不會匹配路徑分隔符)
  • [...] 匹配方括號中出現的字符中的任意一個,當方括號中第一個字符為^!時,則表示不匹配方括號中出現的其他字符中的任意一個,類似js正則表達式中的用法
  • !(pattern|pattern|pattern) 匹配任何與括號中給定的任一模式都不匹配的
  • ?(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或1次,類似于js正則中的(pattern|pattern|pattern)?
  • +(pattern|pattern|pattern) 匹配括號中給定的任一模式至少1次,類似于js正則中的(pattern|pattern|pattern)+
  • *(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或多次,類似于js正則中的(pattern|pattern|pattern)*
  • @(pattern|pattern|pattern) 匹配括號中給定的任一模式1次,類似于js正則中的(pattern|pattern|pattern)

下面以一系列例子來加深理解

  • * 能匹配 a.js,x.y,abc,abc/,但不能匹配a/b.js
  • *.* 能匹配 a.js,style.css,a.b,x.y
  • */*/*.js 能匹配 a/b/c.js,x/y/z.js,不能匹配a/b.js,a/b/c/d.js
  • ** 能匹配 abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用來匹配所有的目錄和文件
  • **/*.js 能匹配 foo.js,a/foo.js,a/b/foo.js,a/b/c/foo.js
  • a/**/z 能匹配 a/z,a/b/z,a/b/c/z,a/d/g/h/j/k/z
  • a/**b/z 能匹配 a/b/z,a/sb/z,但不能匹配a/x/sb/z,因為只有單**單獨出現才能匹配多級目錄
  • ?.js 能匹配 a.js,b.js,c.js
  • a?? 能匹配 a.b,abc,但不能匹配ab/,因為它不會匹配路徑分隔符
  • [xyz].js 只能匹配 x.js,y.js,z.js,不會匹配xy.js,xyz.js等,整個中括號只代表一個字符
  • [^xyz].js 能匹配 a.js,b.js,c.js等,不能匹配x.js,y.js,z.js

當有多種匹配模式時可以使用數組  

gulp.src(['js/*.js','css/*.css','*.html'])

使用數組的方式還有一個好處就是可以很方便的使用排除模式,在數組中的單個匹配模式前加上!即是排除模式,它會在匹配的結果中排除這個匹配,要注意一點的是不能在數組中的第一個元素中使用排除模式

1 gulp.src([*.js,'!b*.js']) //匹配所有js文件,但排除掉以b開頭的js文件 
2 gulp.src(['!b*.js',*.js]) //不會排除任何文件,因為排除模式不能出現在數組的第一個元素中

此外,還可以使用展開模式。展開模式以花括號作為定界符,根據它里面的內容,會展開為多個模式,最后匹配的結果為所有展開的模式相加起來得到的結果。展開的例子如下:

  • a{b,c}d 會展開為 abd,acd
  • a{b,}c 會展開為 abc,ac
  • a{0..3}d 會展開為 a0d,a1d,a2d,a3d
  • a{b,c{d,e}f}g 會展開為 abg,acdfg,acefg
  • a{b,c}d{e,f}g 會展開為 abdeg,acdeg,abdeg,abdfg

2,glup.dest()

gulp.dest()方法是用來寫文件的,其語法為:

gulp.dest(path[,options])

path為寫入文件的路徑
options為一個可選的參數對象,通常我們不需要用到

這個方法我們需要理解好傳入的路徑參數與最終生成的文件的關系。

gulp的使用流程一般是這樣子的:首先通過gulp.src()方法獲取到我們想要處理的文件流,然后把文件流通過pipe方法導入到gulp的插件中,最后把經過插件處理后的流再通過pipe方法導入到gulp.dest()中,gulp.dest()方法則把流中的內容寫入到文件中,這里首先需要弄清楚的一點是,我們給gulp.dest()傳入的路徑參數,只能用來指定要生成的文件的目錄,而不能指定生成文件的文件名,它生成文件的文件名使用的是導入到它的文件流自身的文件名,所以生成的文件名是由導入到它的文件流決定的,即使我們給它傳入一個帶有文件名的路徑參數,然后它也會把這個文件名當做是目錄名,例如:

1 var gulp = require('gulp');
3 gulp.src('script/jquery.js')
5       .pipe(gulp.dest('dist/foo.js'));
6 
7 //最終生成的文件路徑為 dist/foo.js/jquery.js,而不是dist/foo.js

要想改變文件名,可以使用插件gulp-rename

gulp.dest(path)生成的文件路徑是我們傳入的path參數后面再加上gulp.src()中有通配符開始出現的那部分路徑。

1 var gulp = reruire('gulp'); //有通配符開始出現的那部分路徑為 **/*.js
2 
3 gulp.src('script/**/*.js') .pipe(gulp.dest('dist')); //最后生成的文件路徑為 dist/**/*.js
4 
5 //如果 **/*.js 匹配到的文件為 jquery/jquery.js ,則生成的文件路徑為 dist/jquery/jquery.js

3,gulp.task()

gulp.task方法用來定義任務,內部使用的是Orchestrator,其語法為:

gulp.task(name[, deps], fn)

name 為任務名
deps 是當前定義的任務需要依賴的其他任務,為一個數組。當前定義的任務會在所有依賴的任務執行完畢后才開始執行。如果沒有依賴,則可省略這個參數
fn 為任務函數,我們把任務要執行的代碼都寫在里面。該參數也是可選的。

1 gulp.task('mytask', ['array', 'of', 'task', 'names'], function() {//定義一個有依賴的任務
2 
3 // Do something
4 
5 });

執行多個任務時怎么控制任務執行的順序

//只要執行default任務,就相當于把one,two,three這三個任務執行了

gulp.task('default',['one','two','three']);

如果任務相互之間沒有依賴,任務會按你書寫的順序來執行,如果有依賴的話則會先執行依賴的任務。

是如果某個任務所依賴的任務是異步的,就要注意了,gulp并不會等待那個所依賴的異步任務完成,而是會接著執行后續的任務。例如:

1 gulp.task('one',function(cb){
2 var stream = gulp.src('client/**/*.js')
3           .pipe(dosomething()) //dosomething()中有某些異步操作
4           .pipe(gulp.dest('build'));
5   return stream;
6 });
7 gulp.task('two',['one'],function(){
8    console.log('two is done');
9 });

上面的例子中我們執行two任務時,會先執行one任務,但不會去等待one任務中的異步操作完成后再執行two任務,而是緊接著執行two任務。所以two任務會在one任務中的異步操作完成之前就執行了。

那如果我們想等待異步任務中的異步操作完成后再執行后續的任務,該怎么做呢?
有三種方法可以實現:
第一:在異步操作完成后執行一個回調函數來通知gulp這個異步任務已經完成,這個回調函數就是任務函數的第一個參數。

 1 gulp.task('one',function(cb){
 2 //cb為任務函數提供的回調,用來通知任務已經完成
 3 //one是一個異步執行的任務
 4   setTimeout(function(){
 5     console.log('one is done');
 6     cb(); //執行回調,表示這個異步任務已經完成
 7   },5000);
 8 });
 9 //這時two任務會在one任務中的異步操作完成后再執行
10 gulp.task('two',['one'],function(){
11    console.log('two is done');
12 });

第二:定義任務時返回一個流對象。適用于任務就是操作gulp.src獲取到的流的情況。

gulp.task('one',function(cb){

var stream = gulp.src('client/**/*.js')
          .pipe(dosomething()) //dosomething()中有某些異步操作
          .pipe(gulp.dest('build'));
return stream;
});
gulp.task('two',['one'],function(){
   console.log('two is done');
});

第三:返回一個promise對象,例如

 1 var Q = require('q'); //一個著名的異步處理的庫 https://github.com/kriskowal/q
 2 gulp.task('one',function(cb){
 3   var deferred = Q.defer();
 4   // 做一些異步操作
 5   setTimeout(function() {
 6      deferred.resolve();
 7   }, 5000);
 8   return deferred.promise;
 9 });
10 
11 gulp.task('two',['one'],function(){
12   console.log('two is done');
13 });

4,gulp.watch()

gulp.watch()用來監視文件的變化,當文件發生變化后,我們可以利用它來執行相應的任務,例如文件壓縮等。其語法為

gulp.watch(glob[, opts], tasks)

glob 為要監視的文件匹配模式,規則和用法與gulp.src()方法中的glob相同。
opts 為一個可選的配置對象,通常不需要用到
tasks 為文件變化后要執行的任務,為一個數組

1 gulp.task('uglify',function(){
2   //do something
3 });
4 gulp.task('reload',function(){
5   //do something
6 });
7 gulp.watch('js/**/*.js', ['uglify','reload']);

gulp.watch()還有另外一種使用方式:

gulp.watch(glob[, opts, cb])

glob和opts參數與第一種用法相同
cb參數為一個函數。每當監視的文件發生變化時,就會調用這個函數,并且會給它傳入一個對象,該對象包含了文件變化的一些信息,type屬性為變化的類型,可以是added,changed,deletedpath屬性為發生變化的文件的路徑

1 gulp.watch('js/**/*.js', function(event){
2     console.log(event.type); //變化類型 added為新增,deleted為刪除,changed為改變 
3     console.log(event.path); //變化的文件的路徑
4 }); 

 

博客轉載http://www.cnblogs.com/2050/p/4198792.html

 


文章列表


不含病毒。www.avast.com
全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()