gulp的使用方法

一、安裝gulpcss

npm install --save-dev gulp
複製代碼

二、建立gulpfile.js文件html

var gulp = require("gulp");
gulp.task("default", function() {
    console.log("hello");
})
複製代碼

三、gulp命令node

3.1 gulp.src(globs,[options])git

做用:將匹配的文件轉化爲數據流而後經過pipe方法,將數據流傳遞給對應的插件進行處理。github

globs爲路徑匹配模式,相似正則表達式,可是跟正則表達式是不一樣的。能夠直接寫真實的頁面路徑。正則表達式

好比須要對a.txt這個文件進行某種處理,能夠這樣引入a.txt文件npm

gulp.src("a.txt")
複製代碼

3.2 gulp.dest(path[,options])gulp

做用:將pipe進來的數據流轉化爲文件。注意文件名是不會變的。若是要改文件名就須要相應的gulp插件數組

gulp.task("default", function() {
    gulp.src("aa.txt")
        .pipe(gulp.dest("test"));
})
複製代碼

path爲文件將被寫入的路徑(輸出目錄)。也可傳入一個函數,在函數中返回相應的路徑。promise

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

做用:定義一個使用gulp任務

  • name類型爲字符串,含義爲任務的名字。
  • deps一個包含任務列表的數組,這些任務會在你當前任務運行以前完成(若是任務是異步任務的話,還須要作進一步的特殊處理)。數組中的任務並非按照他們在數組中的前後順序執行,而是是併發執行的
  • fn 該函數定義任務所要執行的一些操做

建立一個任務a,打印一個hello world。

gulp.task("a",function(){
  console.log("hello world");
})
複製代碼

3.4 gulp.watch(glob [, opts], tasks) 或 gulp.watch(glob [, opts, cb])

監視文件,而且在文件變更的時候執行某些任務。

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

好比監視js文件,當js文件變更的時候,壓縮js文件到dest文件夾。文件變更包括:一、新增文件,二、改變文件內容,三、刪除文件,四、重命名文件

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
gulp.task("compassJs", function() {
    gulp.src("*.js")
        .pipe(uglify())
        .pipe(gulp.dest("test"));
})
gulp.task("default", function() {
    gulp.watch("*.js", ["compassJs"]);
})
複製代碼

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

好比監視js文件,當文件變更的時候,執行某些操做。一、新增文件,二、改變文件內容,三、刪除文件,四、重命名文件

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
gulp.task("default", function() {
    gulp.watch("*.js", function(event) {
        console.log(event.path, event.type);
    });
})
複製代碼

進階篇

一、gulp.src(globs,[options])

gulp引入須要處理的文件,採用的方法是glob匹配文件路徑。glob匹配具體規則以下

1.一、glob 模式匹配

點擊在github上查看完整文檔

    • 匹配0個或者多個任意字符
  • ? 匹配任意一個字符
  • [...]範圍匹配,若是字符在中括號範圍內,則匹配。使用方法相似正則表達式的中括號。若是中括號中以!或者^開頭,則當字符不在中括號中時才匹配
  • !(pattern|pattern|pattern) 不知足括號中的全部模式則匹配
  • ?(pattern|pattern|pattern)匹配括號中的0個或者多個模式
  • +(pattern|pattern|pattern) 匹配括號中 1 或 更多模式,或者模式之間的組合
  • *(pattern|pattern|pattern)匹配括號中的0個或者多個模式,或者任意模式的組合。
  • @(pattern|pattern|patter)知足 1 個括號中的模式則匹配
  • ** 單獨使用時匹配n級目錄或者n級目錄+文件,若是跟其餘模式混用則匹配某個目錄或者某個文件

glob的使用方法:

//其中pattern 爲glob模式,options爲glob配置選項,若是沒有能夠省略。function爲匹配的回調函數,參數er爲錯誤對象,files爲匹配成功的文件名數組。
var glob = require("glob")
glob(pattern, options, function (er, files) {
  // files is an array of filenames.
  // If the `nonull` option is set, and nothing
  // was found, then files is [pattern]
  // er is an error object or null.
})
複製代碼

glob的使用案例:

目錄結構:

--glob.js
--a.txt
--b.txt
--node_modules
複製代碼

假設有一個glob.js文件,代碼以下,在glob同級目錄下有a.txt,b.txt兩個文件。命令行執行node glob.js。則能夠匹配到a.txt,b.txt 兩個文件:

glob("*.txt", {}, function(err, files) {
    console.log("files:", files); // files:["a.txt","b.txt"]
});
複製代碼

1.1.1 點的特殊處理

目錄名或者文件名若是以 . 開頭,只有模式中對應部分以 . 開頭才能匹配。

若是在option中設置dot:true,glob就會把.當成普通的字符來處理,這時候就可使用*或者?來匹配.了。

1.1.2 matchBase匹配

若是option中設置了matchBase爲true,則glob會遍歷同級目錄及其子目錄下任意符合匹配模式的文件

1.1.3 空輸出

若是沒有文件或者目錄符合模式,則返回一個空數組

1.2 完整的測試案例

目錄結構

+--b
| +--b.txt
+--c
| +--c2
| | +--c.txt
+--..git
+--a.txt
+--a1.txt
+--aa.txt
+--ab.txt
+--ac.txt
+--b.txt
+--ba.txt
+--c.txt
+--glob.js
複製代碼

glob.js代碼及輸入結果以下:

var glob = require("glob");
// *測試
glob("*.txt", {}, function(err, files) {
    console.log("*符號測試", files);   
});

//?測試
glob("?.txt", {}, function(err, files) {
    console.log("?符號測試", files);
});
//[]測試
glob("a[a-z].txt", {}, function(err, files) {
    console.log("[]符號測試", files);
});
// !()測試
glob("!(a|b).txt", {}, function(err, files) {
    console.log("!()符號測試", files);
});
// ?()測試
glob("?(a|b).txt", {}, function(err, files) {
    console.log("?()符號測試", files);
});
// +()測試
glob("+(a|b).txt", {}, function(err, files) {
    console.log("+()符號測試", files);
});
// *()測試
glob("*(a|b).txt", {}, function(err, files) {
    console.log("*()符號測試", files);
});

// @()測試
glob("@(a|b).txt", {}, function(err, files) {
    console.log("@()符號測試", files);
});

// **測試
glob("**", {}, function(err, files) {
    console.log("**符號測試", files);
});
// .測試
glob("?.git", {}, function(err, files) {
    console.log(".符號測試", files);
});
// .測試
glob("?.git", { dot: true }, function(err, files) {
    console.log(".符號測試dot爲true", files);
});

// matchBase測試外部終端配置
glob("*.txt", { matchBase: true }, function(err, files) {
    console.log("matchBase測試", files);
});

// 不匹配測試
glob("*.png", { matchBase: true }, function(err, files) {
    console.log("不匹配測試", files);
});

如下爲代碼的輸出結果:
/*
*符號測試 [ 'a.txt',
  'a1.txt',
  'aa.txt',
  'ab.txt',
  'ac.txt',
  'b.txt',
  'ba.txt',
  'c.txt' ]
?符號測試 [ 'a.txt', 'b.txt', 'c.txt' ]
[]符號測試 [ 'aa.txt', 'ab.txt', 'ac.txt' ]
!()符號測試 [ 'a1.txt', 'aa.txt', 'ab.txt', 'ac.txt', 'ba.txt', 'c.txt' ]
?()符號測試 [ 'a.txt', 'b.txt' ]
+()符號測試 [ 'a.txt', 'aa.txt', 'ab.txt', 'b.txt', 'ba.txt' ]
*()符號測試 [ 'a.txt', 'aa.txt', 'ab.txt', 'b.txt', 'ba.txt' ]
@()符號測試 [ 'a.txt', 'b.txt' ]
.符號測試 []
.符號測試dot爲true [ '..git' ]
**符號測試 [ 'a.txt',
  'a1.txt',
  'aa.txt',
  'ab.txt',
  'ac.txt',
  'b',
  'b.txt',
  'b/b.txt',
  'ba.txt',
  'c',
  'c.txt',
  'c/c2',
  'c/c2/c.txt',
  'glob.js' ]
matchBase測試 [ 'a.txt',
  'a1.txt',
  'aa.txt',
  'ab.txt',
  'ac.txt',
  'b.txt',
  'b/b.txt',
  'ba.txt',
  'c.txt',
  'c/c2/c.txt' ]
不匹配測試 []
*/
複製代碼

1.3 options選項

glob的options是經過gulp.src(globs,[options])中的options傳入的。gulp的option處理包含glob的全部配置選項外還擴展了一些本身的內容。

1.3.1 options.buffer

默認options.buffer爲true。gulp.src將文件轉爲vinyl類型的數據流的時候,默認是以buffer存儲數據內容的。gulp的插件默認也是處理buffer類型的數據。buffer類型的數據流有個缺點就是須要所有讀取完文件才能處理。這樣處理速度就會相對較慢。

能夠將options.buffer設置爲false,這樣gulp.src將文件轉爲vinyl類型的數據流的時候,就會採用stream的形式存儲數據內容。這樣能夠提升處理大文件的速度。缺點支持stream類型的插件較少。

1.3.2 options.read

默認options.read爲true。若是設置爲false。gulp.src就不會去讀取文件

1.3.3 options.base

字符串類型,默認返回路徑中glob模式以前的字符串或者路徑中匹配成功以前的字符串

以上爲glob經常使用的使用方法,完整的使用方法須要在github上查看。glob的options是經過gulp.src(globs,[options])的options傳入的。

二、 vinyl-fs

gulp.src會將匹配的文件轉化爲vinyl類型的數據流,而後經過pipe方法將流傳遞給對應的插件進行處理。 gulp只支持vinyl類型的數據流,不支持常規的nodejs數據流。

2.1 vinyl是什麼

vinyl是一個文件格式,經過它能夠很方面的描述一個文件,包括文件的路徑、文件名和內容,它也能夠很方便的設置或者獲取文件的內容。優勢就是跨平臺,能夠將不一樣操做系統的文件轉化爲統一的形式。

建立一個vinyl類型的文件

//建立vinyl方法 new Vinyl(options)
var Vinyl = require("vinyl");
var jsFile = new Vinyl({
    cwd: "/",
    base: "/test",
    path: "/test/file.js",
    contents: new Buffer("var x=123")
})
複製代碼

其中各個選項的含義以下

  • cwd——The current working directory of the file 文件當前工做目錄,默認爲process.cwd()

頁面目錄結果以下

+--b
| +--aa.txt
+--aa.txt
複製代碼

程序以下:

gulp.task("default", function() {
    gulp.src("aa.txt", { cwd: "b" })
        .pipe(gulp.dest("test"))
})
複製代碼

若是沒有給gulp.src傳{cwd:"b"} gulp選擇的文件爲跟b文件夾同目錄的aa.txt 。如今由於程序傳了{cwd:"b"},因此如今選擇的文件爲b文件夾下的aa.txt

  • base——相對路徑,默認爲process.cwd()
  • path——文件的完整路徑
  • contents——buffer形式(二進制)的文件內容

參考來源:

vinyl的npm地址

三、gulp.dest(path[,options])

3.1 options 選項

  • cwd 輸出目錄的cwd參數,只在所給的輸出目錄是相對路徑時有效

程序1:

gulp.task("default", function() {
    gulp.src("aa.txt")
        .pipe(gulp.dest("test"));
})
複製代碼

程序2:

gulp.task("default", function() {
    gulp.src("aa.txt")
        .pipe(gulp.dest("test", { cwd: "hello" }));
})
複製代碼

程序1的執行結果

+--test
| +--aa.txt
複製代碼

程序2的執行結果

+--hello
| +--test
| | +--aa.txt
複製代碼

程序2會先在目錄中生成hello文件夾,而後再輸出gulp.dest結果。

  • mode 八進制權限字符,用以定義全部在輸出目錄中所建立的目錄的權限。

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

異步任務按順序執行

gulp.task("a", function() {
    console.log("a");
})
gulp.task("b", function() {
    setTimeout(() => {
        console.log("b");
    }, 100);
})
gulp.task("default", ["a", "b"], function() {
    console.log("default");
})
//執行結果控制檯輸出 a default b
複製代碼

若是要確保依賴任務徹底執行完畢,再執行當前任務,也就是須要序列化的執行任務,須要作兩件事情。

  1. 須要給一個提示,來告知task何時執行完畢
  2. 而且須要再給一個提示,來告知任務之間的依賴關係

方法有3個:

4.1 使用回調函數

有兩個任務a、b,b任務裏有一個異步函數。若是不作特殊處理,輸出結果以下。

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
    console.log("a");
})
gulp.task("b", function() {
    setTimeout(() => {
        console.log("b");
    }, 100);
})
gulp.task("default", ["a", "b"], function() {
    console.log("default");
})
//輸出結果 a default b
複製代碼

這並非咱們想要的,咱們但願a、b執行完了再執行default。咱們能夠在b任務中調用一個callback函數,來實現咱們的要求

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
    console.log("a");
})
gulp.task("b", function(cb) {
    setTimeout(() => {
        console.log("b");
        cb()
    }, 100);
})
gulp.task("default", ["a", "b"], function() {
    console.log("default");
})
// 執行結果 a b default
複製代碼

4.2 返回一個stream

有a、b兩個任務,b任務須要去執行一個異步任務——讀取一張圖片。

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
    console.log("a");
})
gulp.task("b", function() {
    gulp.src("b.png")
        .pipe(map(function(data, callback) {
            console.log("b");
            callback(null, data)
        }))
        .pipe(gulp.dest("test"));
})
gulp.task("default", ["a", "b"], function() {
    console.log("default");
})
// 執行結果 a default b
複製代碼

default任務在b任務執行完成以前執行了,這不符合咱們的要求,咱們能夠在b任務中返回一個stream,來達到序列化的要求。

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
    console.log("a");
})
gulp.task("b", function() {
    return gulp.src("b.png")
        .pipe(map(function(data, callback) {
            console.log("b");
            callback(null, data)
        }))
        .pipe(gulp.dest("test"));
})
gulp.task("default", ["a", "b"], function() {
    console.log("default");
})
//執行結果 a b default
複製代碼

4.3 返回一個promise

咱們修改4.1中第一個程序,把它由callback實現序列化改爲經過promise來實現序列化

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
gulp.task("a", function() {
    console.log("a");
})
gulp.task("b", function() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(() => {
            console.log("b");
            resolve();
        }, 100);
    })
    return p;

})
gulp.task("default", ["a", "b"], function() {
    console.log("default");
})
//輸出結果 a、b、default
複製代碼

五、gulp的報錯處理

執行gulp任務的時候常常會遇到gulp報錯的狀況,gulp對於錯誤的處理很是糟糕,一旦報錯gulp就會退出工做流,而gulp給出的錯誤信息,幾乎沒啥參考價值的。

好比有以下一個程序,監視a.js文件,當a.js文件發生改變的時候就壓縮a.js。壓縮後的文件放在dest文件夾下。

gulpfile.js代碼以下

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
var pump = require("pump");
gulp.task("compassJs", function() {
    gulp.src("a.js")
        .pipe(uglify())
        .pipe(gulp.dest("dest"));
})
gulp.task("default", function() {
    gulp.watch("a.js", ["compassJs"]);
})
複製代碼

當咱們在a.js文件中不當心輸入這麼一段代碼,gulp就會退出工做流。

import {} from "module";
複製代碼

這不是咱們想要的,咱們但願gulp能繼續工做,這樣當咱們刪掉這段錯誤代碼的時候,gulp能夠繼續壓縮a.js文件,不須要咱們從新再命令行輸入gulp命令

gulp有不少插件能夠處理錯誤,這裏拋磚引玉介紹兩種,一種是用來處理js報錯的,一種是用來處理sass報錯的

5.1 js報錯處理

推薦插件:pump

var gulp = require("gulp");
var glob = require("glob");
var fs = require("fs");
var map = require("map-stream");
var uglify = require("gulp-uglify");
var pump = require("pump");
gulp.task("compassJs", function() {
    pump([
        gulp.src("a.js"),
        uglify(),
        gulp.dest("test")
    ])
})
gulp.task("default", function() {
    gulp.watch("a.js", ["compassJs"]);
})
複製代碼

5.2 sass報錯處理

推薦插件:plumber

咱們的任務是監視c.scss文件,當文件變更的時候就時時把它編譯爲css文件。

c.scss文件內容以下

html,
body {
    width: 100px;
    height: 100px;
}
複製代碼

gulpfile.js代碼以下

var gulp = require("gulp");
var sass = require("gulp-sass");
var plumber = require("gulp-plumber");
gulp.task("compilecss", function() {
    gulp.src("c.scss")
        .pipe(sass())
        .pipe(gulp.dest("dest"));
})
gulp.task("default", function() {
    gulp.watch("c.scss", ["compilecss"]);
})
複製代碼

當咱們在c.scss文件中不當心輸入一段錯誤代碼,並保存的時候,gulp就會報錯,並退出工做流

好比c.scss文件改爲以下(多了一個img標籤)。gulp就會退出工做流

html,
body {
    width: 100px;
    height: 100px;
}
img
複製代碼

gulp報錯:

[10:41:26] Using gulpfile ~\Desktop\博客內容\gulp的使用\gulp-test\gulpfile.js
[10:41:26] Starting 'default'...
[10:41:26] Finished 'default' after 11 ms
[10:41:33] Starting 'compilecss'...
[10:41:33] Finished 'compilecss' after 8.41 ms

events.js:160
      throw er; // Unhandled 'error' event
      ^
 Error: c.scss
Error: Invalid CSS after "img": expected "{", was ""
        on line 7 of c.scss
>> img
   ---^

    at options.error (C:\Users\寄居蟹黃粥\Desktop\博客內容\gulp的使用\gulp-test\node_modules\_node-sass@4.7.2@node-sass\lib\index.js:291:26)
複製代碼

咱們可使用plumber來避免這種狀況,修改後的gulpfile.js代碼以下

var gulp = require("gulp");
var sass = require("gulp-sass");
var plumber = require("gulp-plumber");
gulp.task("compilecss", function() {
    gulp.src("c.scss")
        .pipe(plumber({
            errorHandler: function(event) {
                console.log(event.message);
                this.emit('end');
            }
        }))
        .pipe(sass())
        .pipe(gulp.dest("dest"));
})
gulp.task("default", function() {
    gulp.watch("c.scss", ["compilecss"]);
})
複製代碼

這樣當scss文件出錯的時候,gulp只會在命令行打印錯誤,並不會退出工做流,監視工做還能夠繼續。

關於gulp網上還有其餘插件和方法,剛興趣能夠自行google

相關文章
相關標籤/搜索