一、安裝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任務
建立一個任務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上查看完整文檔
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")
})
複製代碼
其中各個選項的含義以下
頁面目錄結果以下
+--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
參考來源:
vinyl的npm地址
三、gulp.dest(path[,options])
3.1 options 選項
程序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結果。
四、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
複製代碼
若是要確保依賴任務徹底執行完畢,再執行當前任務,也就是須要序列化的執行任務,須要作兩件事情。
方法有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