gulp的入門介紹

gulp的簡單介紹

gulp是一個即grunt後出現的一個前端構建工具,跟grunt相比,gulp的API很少並且很簡單,使用nodejs中stream來讀取和操作數據,其速度比grunt更快,下面讓我們來學習一下如何使用gulp快速構建你的項目。

本文主要介紹

  • gulp的安裝和使用

  • gulp的API

  • gulp的常用插件

gulp的安裝和使用

1.全局安裝gulp

npm install --global gulp

2.作爲項目依賴安裝gulp

$ npm install --save-dev gulp

3.使用gulp

1.在你的文件目錄下面建立一個package.jsongulpfile.js的文件。

package.json:此文件被npm用於存儲項目的元數據,以便將此項目發佈爲npm模塊。你可以在此文件中列出項目依賴的gulp插件,放置於devDependencies配置字段內;
gulpfile:用來配置或定義任務(task)並加載gulp插件的。

2.安裝gulp插件

 $ npm install --save-dev gulp-uglify

--save-dev和--save的區別

如果只寫上--save,gulp插件在package.json的dependencies裏面保存,而寫--save-dev 的話,gulp插件會保存在package.json的devDependencies,這裏有關於這兩個屬性的區別http://www.cnblogs.com/jes_sh...

安裝包的兩種方式

npm insatll

devDependencies和dependencies都會安裝

$ npm install --production

只安裝dependencies而不安裝devDependencies。

$ npm install packagename

那麼只會安裝dependencies,而不安裝devDependencies。

$ npm install packagename --dev

devDependencies和dependencies都會安裝

舉個例子

我們新建一個文件夾只有package.json文件,執行 會默認讀取package.json的
devDependencies和dependencies裏面的屬性,並且安裝devDependencies和dependencies下面的包。
如下所示,會安裝gulp和gulp-concat,然後還會讀取gulp和gulp-concat
裏面的dependencies裏面的包,在安裝gulp和gulp-concat所依賴的包,但是這個時候並不會安裝devDependencies裏面的包了

{
  "name": "grunt_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies":{
    "gulp": "^3.9.1"
  },
  "devDependencies": {
    "gulp-concat": "^2.6.0"
  },
  "author": "",
  "license": "ISC"
}
$ gulp npm install --save stream-combiner2
{
  "name": "application-name",
  "version": "0.0.1",
  "devDependencies": {
    "del": "^2.2.1",
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.0",
    "gulp-load-plugins": "^1.2.4",
    "gulp-uglify": "^1.5.4",
    "pump": "^1.0.1"
  },
  "dependencies": {
    "stream-combiner2": "^1.1.1"
  }
}

3.編寫gulpfile.js

  var gulp = require('gulp');
    var uglify = require('gulp-uglify');
    gulp.task('uglifyTask', function (cb) {
    return gulp.src('www/**')
        .pipe(uglify())
        .pipe(gulp.dest('dest'));
    })

4.運行task

gulp uglifyTask

執行上述命令,就會執行uglifyTask這個task,如果只輸入gulp 那麼會默認執行default這個任務;

如果gulpfile中沒有設置default這個任務,直接執行gulp,就會拋出以下錯誤

➜$ gulp
[22:40:37] Using gulpfile ~/WebstormProjects/gulp/gulpfile.js
[22:40:37] Task 'default' is not in your gulpfile
[22:40:37] Please check the documentation for proper gulpfile formatting

gulp的API

  • gulp.src(globs,option)

  • gulp.dest(path, options)

  • task(name, deps, fn)

  • gulp.watch(glob , opts, tasks) 或 gulp.watch(glob , opts, cb)

就這四個API是不是特別少,在介紹這些API之前先說一下gulp的工作方式,gulpfile.js充分利用了Node.js的 Streams(流) API ,首先獲取到需要的stream,然後可以通過stream的pipe(管道)方法把流導入到你想要的地方,比如Gulp的插件中,經過插件處理後的流又可以繼續導入到其他插件中,當然也可以把流寫入到文件中。

1.gulp.src(globs,option)

gulp.src就是輸出符合所提供的匹配模式(glob)或者匹配模式的數組(array of globs)的文件。 將返回一個流,可以通過管道pipe輸入別的gulp插件,內容不是原始的文件流,而是一個虛擬文件對象流(這個是看一篇介紹說的,具體理解不深),我們可以簡單理解爲讀取一個符合globs匹配的文件

globs是文件匹配模式的一個字符串或者一個數組,下面是常用文件匹配模式

  • * 匹配任意數量的字符,但不匹配 /

  • ? 匹配單個字符,但不匹配 /

  • ** 匹配任意數量的字符,包括 /,只要它是路徑中唯一的一部分

  • [pattern,pattern1] 匹配方括號中出現的字符中的任意一個,當方括號中第一個字符爲^或!時,則表示不匹配方括號中出現的其他字符中的任意一個,類似js正則表達式中的用法

  • ! 在模式的開頭用於排除一個匹配模式所匹配的任何文件

下面以一系列例子來加深印象,我的目錄結構是這樣的


'www/*'            匹配  www/a.js www/js
 
'www/?.js'           匹配  www/a.js

'www/**/*.js'        匹配 www/所有二級目錄下的js

['www/**/*.js','src/**/*.js'] 匹配 www和src下面的所有的子級目錄下面的js文件;

['www/**/*.js','!www/*.js'] 匹配不包含www下面的a.js的所有其他的js文件;

option通過 glob-stream 所傳遞給 node-glob 的參數,除了 node-glob 和 glob-stream 所支持的參數外,gulp 增加了一些額外的選項參數:

1.options.buffer 類型: Boolean 默認值: true

那麼將會以 stream 方式返回 file.contents 而不是文件 buffer 的形式返回;

2.options.read 類型: Boolean 默認值: true

如果該項被設置爲 false, 那麼 file.contents 會返回空值(null),也就是並不會去讀取文件。

3.ptions.base 類型 string

修改 base的值 默認的base的值爲通配符開始出現之前那部分路徑,如果設置了base值,那麼將依照這個base值爲基準

 return gulp.src('www/js/**/*.js') //假設匹配上的是www/js/module/a.js,那麼base是www/js
        .pipe($.uglify())
        .pipe(gulp.dest('dest')); //dest輸出的是 dest/module/a.js 
        
  return gulp.src('www/js/**/*.js',{base:'www'}) //設定了base,那麼base是www
        .pipe($.uglify())
        .pipe(gulp.dest('dest')); //dest輸出的是 dest/js/module/a.js        

2.gulp.dest(path, options)

path:文件輸出的目錄,只能是目錄地址,如果包含文件名,那麼會把文件名也當做目錄的一部分建對應的路徑,path將替換gulp.src裏面的base生成對應的目錄存放文件。

gulp.task('uglifyTask', function (cb) {
    return gulp.src('www/js/**/*.js',{base:'www'})
        .pipe($.uglify())
        .pipe($.rename({extname: '.min.js'}))
        .pipe(gulp.dest('dest/uglfy.min.js'));
})


options,這個一般不用,這裏就不做介紹了,需要了解的可以去官方api進行了解;

3.task(name, deps, fn)

gulp.task 定義一個任務,name類型:string,這個任務的名稱;deps類型:array,這個任務依賴的其他任務;fn類型:function 任務的具體操作,有一個參數,是執行完的回調函數cb

這個方法比較簡單,這裏我主要講一下執行順序

/** 壓縮 **/
gulp.task('uglifyTask',['clean:dest'],function (cb) {
    console.log('uglifyTask執行')
    return gulp.src('www/js/**/*.js',{base:'www'})
        .pipe($.uglify())
        .pipe($.rename({extname: '.min.js'}))
        .pipe(gulp.dest('dest/uglfy.min.js'));
})
/** 刪除 **/
    gulp.task('clean:dest', function (cb) {
         console.log('dest已經執行完畢')
         del([  
            'dest/**/*'
        ])
    })
gulp uglifyTask

上面代碼我們會認爲首先輸出‘dest已經執行完畢’,‘然後輸出uglifyTask執行’,結果我們去命令行輸出的結果是這個樣子滴

➜  gulp gulp uglifyTask
[00:10:54] Using gulpfile ~/WebstormProjects/gulp/gulpfile.js
[00:10:54] Starting 'clean:dest'...
dest已經執行完畢
➜  gulp 

只輸出了dest已經執行完畢,這是爲什麼?

原來,默認的,task 將以最大的併發數執行,也就是說,gulp 會一次性運行所有的 task 並且不做任何等待。如果你想要創建一個序列化的 task 隊列,並以特定的順序執行,你需要在依賴的task裏面給出提示,告訴這個task已經執行完畢

提示的三種方式:

  1. 返回一個流

  2. 返回一個promise

  3. 執行回調函數;

瞭解這些後,上面的我們簡單改變一下,就可以讓clean執行完後,執行uglify的task;

    gulp.task('clean:dest', function (cb) {
        console.log('dest已經執行完畢')
        return del([  //這是返回一個流
            'dest/**/*'
        ])
        // if (err) return cb(err); // 返回 error
        // cb(); 執行回調函數
        // return Promise.resolve('success'); 返回一個成功的promise
    })

4.gulp.watch(glob , opts, tasks) 或 gulp.watch(glob , opts, cb)

gulp.watch 監視文件,並且可以在文件發生改動時候做一些事情。或者執行一些task

glob跟gulp.src的glob相同,這裏就不做介紹了,opts,這個也不經常用API上沒有詳細的介紹。我們主要講一下第三個參數爲tasks 或者 cb的

當第三個參數是tasks,監聽的文件改變的時候會依次執行tasks數組裏面的task,並且會返回一個EventEmitter,可以監聽EventEmitter的change事件,事件的回調函數會被傳入一個名爲 event 的對象。這個對象描述了所監控到的變動:
第三個參數是function,那麼監聽的文件改變的時候,會執行回調函數裏面的內容,同樣的回調函數也有一個event對象,包含以下屬性;

event.type

類型: String

發生的變動的類型:added, changed 或者 deleted。

event.path

類型: String

觸發了該事件的文件的路徑。   
/** 監聽文件變化  tasks**/
var wachEvet=gulp.watch('www/js/**/*.js',['uglifyTask'])
wachEvet.on('change',function(event){
    console.log(event.type+event.path);
})
/** fn **/
gulp.watch('www/js/**/*.js',function(event){
   console.log(event.type+event.path);
})

執行watch 應該建立一個task,然後在命令行裏面輸入 gulp watch

gulp.task('watch',function(){
    gulp.watch('www/js/**/*.js',function(event){
        console.log(event.type+event.path);
    })
})

gulp的常用插件

gulp的插件比較多,這裏我就簡單說幾個常用到的插件,別的插件我們可以通過這個網址去查詢https://www.npmjs.com/browse/...

1.gulp-load-plugins 
作用:自動加載gulp插件
地址:https://www.npmjs.com/package/gulp-load-plugins
使用方法:

var $ = require('gulp-load-plugins')();
$.uglify()
// 同上面一樣
var uglify = require('gulp-uglify');
uglify()

2.gulp-rename
作用:重命名
地址:https://www.npmjs.com/package...
使用方法:

// 字符串形式
gulp.src("./src/main/text/hello.txt")
  .pipe(rename("main/text/hello.js"))
  .pipe(gulp.dest("./dist")); // ./dist/main/text/hello.js 
 
// 方法 
gulp.src("./src/**/hello.txt")
  .pipe(rename(function (path) {
    path.dirname += "/rname";
    path.basename += "-goodbye";
    path.extname = ".md"
  }))
  .pipe(gulp.dest("./dist")); //base=main/text ./dist/main/text/rname/hello-goodbye.md 
 
// 對象
gulp.src("./src/main/text/hello.txt")
  .pipe(rename({
    dirname: "main/text/rname",
    basename: "aloha",
    prefix: "bonjour-",
    suffix: "-hola",
    extname: ".md"
  }))
  .pipe(gulp.dest("./dist")); // ./dist/main/text/rname/bonjour-aloha-hola.md 

3.gulp-uglify
作用:壓縮js代碼,這個只是單純的壓縮,並不像grunt一樣還能改變名稱,所以要配合上面的rename使用
地址:https://www.npmjs.com/package...
使用方法:

gulp.task('uglifyTask',['clean:dest'],function (cb) {
    return gulp.src('www/js/**/*.js',{base:'www'})
        .pipe($.uglify())
        .pipe($.rename({extname: '.min.js'}))
        .pipe(gulp.dest('dest/uglfy.min.js'));
})

4.grunt-concat
作用:合併文件,下面實例會合並一個js,放在dest/concat/all.js
地址:https://www.npmjs.com/package...
使用方法:

gulp.task('concatTask', function (cb) {
    return gulp.src('src/**/*.js')
        .pipe($.concat('concat/all.js'))
        .pipe(gulp.dest('dest'));
})

5.gulp-jshint
作用:語法檢查
地址:
使用方法:

gulp.task('jshint',function(){
   return gulp.src('src/**/*.js')
       .pipe($.jshint())
       .pipe($.jshint.reporter('default')) //使用默認的錯誤提示
      //.pipe(myReporter) 使用map-stream自定義錯誤信息
})

6.del
作用:刪除文件
地址:
使用方法:

gulp.task('clean:dest', function (cb) {
    return del([ 
        'dest/**/*'
    ])
})

7.stream-combiner2
作用:監聽流中的錯誤信息
使用方法:

var combiner = require('stream-combiner2');
var uglify = require('gulp-uglify');
var gulp = require('gulp');

gulp.task('test', function() {
  var combined = combiner.obj([
    gulp.src('bootstrap/js/*.js'),
    uglify(),
    gulp.dest('public/bootstrap')
  ]);

  // 任何在上面的 stream 中發生的錯誤,都不會拋出,
  // 而是會被監聽器捕獲
  combined.on('error', console.error.bind(console));

  return combined;
});

8.lazypipe 
作用:提出流中的公共部分
網址:http://www.gulpjs.com.cn/docs...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章