Gulp-基于流的自動化建構工具
利用gulp,可以快速建構項目,并減少IO操作
gulp在項目開發過程中自動執行任務,友善對目标檔案内容進行IO
官網使用指南http://www.gulpjs.com.cn/docs/getting-started/
Stream流
node.js
安裝
- 安裝node, node -v 檢測安裝成功
- (推薦cnmp) npm install cnpm -g –registry=https://registry.npm.taobao.org, cnmp -v顯示版本号
- cnpm install gulp -g, gulp -v顯示版本号
-
項目檔案根目錄建立package.json,
package.json是基于nodejs項目必不可少的配置檔案,它是存放在項目根目錄的普通json檔案重點内容
-
進入項目檔案夾
d:
cd cperson
- cnpm init, 建立package.json,也可以自己手動建立
- 本地安裝gulp插件,全局安裝gulp是為了執行gulp任務,本地安裝gulp則是為了調用gulp插件的功能
- 建立gulpfile.js,gulpfile.js是gulp的配置檔案,放于根目錄
-
運作gulp,執行認為
常用插件
sass的編譯(gulp-sass)
less編譯 (gulp-less)
重命名(gulp-rename)
自動添加css字首(gulp-autoprefixer)
壓縮css(gulp-clean-css)
js代碼校驗(gulp-jshint)
合并js檔案(gulp-concat)
壓縮js代碼(gulp-uglify)
壓縮圖檔(gulp-imagemin)
自動重新整理頁面(gulp-livereload,谷歌浏覽器親測,谷歌浏覽器需安裝livereload插件)
圖檔緩存,隻有圖檔替換了才壓縮(gulp-cache)
更改提醒(gulp-notify)
gulp是基于任務的
var gulp = require("gulp");
gulp.task("sync", function() {
console.log("同步");
});
gulp.task("async", function() {
setTimeout(function () {
console.log("異步");
done();
}, 2000);
});
運作gulp sync, gulp async
D:\Cperson\front-end\gulp>gulp sync1
[18:32:50] Using gulpfile D:\Cperson\front-end\gulp\gulpfile.js
[18:32:50] Starting 'sync1'...
同步
[18:32:50] Finished 'sync1' after 394 μs
D:\Cperson\front-end\gulp>gulp async
[18:35:01] Using gulpfile D:\Cperson\front-end\gulp\gulpfile.js
[18:35:01] Starting 'async'...
[18:35:01] Finished 'async' after 838 μs
異步
D:\Cperson\front-end\gulp\gulpfile.js:10
done();
^
gulp.task可以有依賴,第二個參數傳入數組,數組裡會*并行處理* gulp.task(“sync”, [“async”, “sync1”, “sync2”], function() { console.log(“done”); });
處理檔案内容
從源src到目的dest,将檔案内容和内聯樣式、腳本進行壓縮,完成.html的優化
優化
- 頁面 js 存放在 ./static/js 下,公共的庫放在 ./static/js/lib 下,公共庫隻壓縮不合并,頁面 js 壓縮并合并。
- 頁面 css 存放在 ./static/css 下,公共的css放在 ./static/css/common 下,公共 css 隻壓縮不合并,頁面 css 壓縮并合并。
-
圖檔資源中小于3kb的圖檔以 base64 方式内聯,圖檔放在 ./static/img 下。
壓縮 js
function minifyAndComboJS(name, encode, files){
var fs = require("fs");
var UglifyJS = require("uglify-js");
var content = "";
files.forEach(function(js){
var minified = UglifyJS.minify(js).code;
content += minified;
});
if(content){
var combo = "static/js/" + name;
}
fs.writeFileSync(combo, content);
gulp.src(combo)
.pipe(gulp.dest("./dist/static/js"));
}
壓縮
js gulp.task("build-js-lib", function(){
gulp.src("./static/js/lib/**/*.js")
.pipe(through.obj(function(file, encode, cb) {
var UglifyJS = require("uglify-js");
var contents = file.contents.toString(encode);
var minified = UglifyJS.minify(contents,
{fromString:true}).code;
file.contents = new Buffer(minified, encode);
cb(null, file, encode);
}))
.pipe(gulp.dest("./dist/static/js/lib"));
});
css
function minifyAndComboCSS(name, encode, files){
var fs = require("fs");
var CleanCSS = require("clean-css");
var content = "";
files.forEach(function(css){
var contents = fs.readFileSync(css, encode);
var minified = new CleanCSS().minify(contents).styles;
content += minified;
});
if(content){
var combo = "static/css/" + name;
}
fs.writeFileSync(combo, content);
gulp.src(combo)
.pipe(gulp.dest("./dist/static/css"));
}
壓縮公共 css
gulp.task("build-common-css", function(){
gulp.src("./static/css/common/**/*.css")
.pipe(through.obj(function(file, encode, cb) {
var CleanCSS = require("clean-css");
var contents = file.contents.toString(encode);
var minified = new CleanCSS().minify(contents).styles;
file.contents = new Buffer(minified, encode);
cb(null, file, encode);
}))
.pipe(gulp.dest("./dist/static/css/common"));
});
處理圖檔
//内聯小圖檔
var imgs = $("img");
for(var i = ; i < imgs.length; i++){
var img = $(imgs[i]);
var src = img.attr("src");
if(/^static\/img/.test(src)){
var stat = fs.statSync(src);
var ext = require("path").parse(src).ext;
if(stat.size <= ){
var head = ext === ".png" ? "data:image/png;base64," : "data:image/jpeg;base64,";
var datauri = fs.readFileSync(src).toString("base64");
img.attr("src", head + datauri);
}
}
}
壓縮 HTML
contents = $.html();
//壓縮 HTML
var HTMLMinifier = require("html-minifier").minify;
var minified = HTMLMinifier(contents, {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
removeAttributeQuotes: true
});
然後,在處理 index.html 的時候,我們可以使用 cheerio 來解析檔案,将要處理的外鍊從文檔中提取出來。
提取 js 和 css 外鍊處理
var $ = require("cheerio").load(contents, {decodeEntities: false});
//處理外鍊 css
var links = $("link");
var cssToCombo = [];
for(var i = ; i < links.length; i++){
var link = $(links[i]);
if(link.attr("rel") === "stylesheet"){
var href = link.attr("href");
if(/^static\/css\/(?!common)/.test(href)){
cssToCombo.push(href);
if(cssToCombo.length == ){
link.attr("href", "static/css/index.min.css");
}else{
link.remove();
}
}
}
}
minifyAndComboCSS("index.min.css", encode, cssToCombo);
//處理外鍊 js
var scripts = $("script");
var jsToCombo = [];
for(var i = ; i < scripts.length; i++){
var s = $(scripts[i]);
//判斷script标簽确實是js
if(s.attr("type") == null
|| s.attr("type") === "text/javascript"){
var src = s.attr("src");
if(src){
//外鍊的js,預設隻處理以/static/開頭的資源
if(/^static\/js\/(?!lib)/.test(src)){
jsToCombo.push(src);
if(jsToCombo.length == ){
s.attr("src", "static/js/index.min.js");
}else{
s.remove();
}
}
}
}
}
minifyAndComboJS("index.min.js", encode, jsToCombo);
API
-
gulp.src(glob[,options])輸出比對模式的檔案
gulp.src(‘client/templates/*.jade’)
.pipe(jade())
.pipe(minify())
.pipe(gulp.dest(‘build/minified_templates’));
glob文法規則
*比對任意 0 或多個任意字元
? 比對任意一個字元
[…] 若字元在中括号中,則比對。若以 ! 或 ^ 開頭,若字元不在中括号中,則比對
!(pattern|pattern|pattern) 不滿足括号中的所有模式則比對
?(pattern|pattern|pattern) 滿足 0 或 1 括号中的模式則比對
+(pattern|pattern|pattern) 滿足 1 或 更多括号中的模式則比對
*(a|b|c) 滿足 0 或 更多括号中的模式則比對
@(pattern|pat*|pat?erN) 滿足 1 個括号中的模式則比對
** 跨路徑比對任意字元
- gulp.dest(path[,options])
gulp.src('./client/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('./build/templates'))
.pipe(minify())
.pipe(gulp.dest('./build/minified_templates'));
能被 pipe 進來,并且将會寫檔案。并且重新輸出(emits)所有資料,是以你可以将它 pipe 到多個檔案夾。如果某檔案夾不存在,将會自動建立它
- gulp.task(name[, deps], fn)
gulp.task('something',function(){
})
task 将以最大的并發數執行,你可以添加依賴
var gulp = require('gulp');
// 傳回一個 callback,是以系統可以知道它什麼時候完成
gulp.task('one', function(cb) {
// 做一些事 -- 異步的或者其他的
cb(err); // 如果 err 不是 null 或 undefined,則會停止執行,且注意,這樣代表執行失敗了
});
// 定義一個所依賴的 task 必須在這個 task 執行之前完成
gulp.task('two', ['one'], function() {
// 'one' 完成後
});
gulp.task('default', ['one', 'two']);
- 監視檔案,并且可以在檔案發生改動時候做一些事情
gulp.watch(glob[,opts], tasks)
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[,opts, cb])
gulp.watch('js/**/*.js', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});