原文鏈接:www.talkingcoder.com
什么是gulp
Gulp是可以自動化執(zhí)行任務的工具。在平時開發(fā)的流程里面,一定有一些動作需要手工的重復的去執(zhí)行,比如:
- 把一個文件拷貝到另外一個位置
- 把多個 JS 或者 CSS 文件合并成一個文件,以減少網(wǎng)絡請求數(shù)
- 對JS文件和CSS進行合并壓縮,以減少網(wǎng)絡流量
- 把Sass或者Less文件編譯成CSS
- 壓縮圖像文件,以減少網(wǎng)絡流量
- 創(chuàng)建一個可以實時刷新頁面內容的本地服務器等等。
只要你覺得有些動作是要重復去做的,一般你就可以把這些動作創(chuàng)建成一個gulp任務,然后在指定的條件下,比如文件發(fā)生變化以后,自動去執(zhí)行這些任務。
gulp特點
- 易于使用 通過代碼優(yōu)于配置的策略,Gulp 讓簡單的任務簡單,復雜的任務可管理。
- 快速構建 利用 node.js 流的威力,你可以快速構建項目并減少頻繁的 IO 操作。前一級的輸出,直接變成后一級的輸入,使得在操作上非常簡單
- 高質量的插件 Gulp 嚴格的插件指南確保插件如你期望的那樣簡潔地工作。
- 易于學習 通過最少的 API,掌握 Gulp 毫不費力,構建工作盡在掌握。
官方文檔解釋
Stream 是 nodejs 各種對象實現(xiàn)的抽象接口。
比如標準輸入是一個流,標準輸出也是一個流。
所有的 stream 對象都是 EventEmitter 的實例,可以發(fā)射事件。
流是一種有起點和終點的數(shù)據(jù)傳輸手段。
上一個的輸出,是下一個的輸入
上一個的輸出,是下一個的輸入
上一個的輸出,是下一個的輸入
gulp中的流
- gulp正是通過流和代碼優(yōu)于配置的策略來盡量簡化任務編寫的工作。
- 類似jquery里的鏈式操作,把各個方法串連起來構建完整的任務。
- 用gulp編寫任務也可看作是用Node.js編寫任務。
- 當使用流時,gulp不需要生成大量的中間文件,只將最后的輸出寫入磁盤,整個過程因此變得非常快。
安裝node
gulp是基于Nodejs的自動任務運行器
安裝Gulp和相關行件用的都是node的包管理工具npm
所以你需要先在電腦上安裝 node,確定在命令行工具的下面可以使用npm這個命令,這樣就能去安裝Gulp了。
node.js官網(wǎng)
安裝好以后,我們可以打開命令行工具,mac 用戶可以使用終端工具,windows 用戶可以找到cmd命令行工具。
安裝gulp
在項目里使用gulp需要
- 在全局范圍內去安裝一下gulp的命令行工具
- 然后在項目里面再去本地安裝gulp
gulp 命令行工具
- 使用 npm install 去安裝 gulp,注意加上一個 -g 的參數(shù),表示在全局范圍內去安裝.
- 一般用 npm 安裝的時候用一個 -g 的參數(shù)就表示,這個安裝的東西會作為命令去執(zhí)行。
- 如果你在mac或linux下遇到了權限問題,在下面這個命令的前面加上 sudo npm install gulp -g 并輸入mac密碼。
npm install -g gulp
安裝完成后可以輸入 gulp --help
如果輸出一些幫助的信息就表示可以gulp命令行成功安裝了
如果安裝不上可以換一下源試試
- 淘寶源
npm install -g gulp --registry=registry.npm.taobao.org - 中國源
npm install -g gulp --registry=[registry.cnpmjs.org] - 官方源
npm install -g gulp --registry=[www.npmjs.org/]
1. 先創(chuàng)建一個目錄
在 mac 和 linux 操作系統(tǒng)下執(zhí)行
mkdir learngulp
在 windows 操作系統(tǒng)下執(zhí)行
md learngulp
2. 使用 命令進入此目錄
cd learngulp
3. 創(chuàng)建項目描述文件 package.json
npm,需要一個叫 package.json 的文件來管理依賴,可以手工去創(chuàng)建這個文件,也可以使用 npm init 這個命令。 輸入
npm init
輸入一些問題答案
name: (zhufeng_automation) learngulp //項目名字,npm init會自動取當前目錄名作為默認名字,這里不需要改,直接確認即可
version: (1.0.0) 1.0.0 //項目版本號,這個大家按自己習慣來定就可以
description: learn gulp //項目說明
entry point: (index.js) index.js // 入門文件 npm start 會執(zhí)行此文件
test command: test.js //測試腳本 npm test 會執(zhí)行此文件
git repository: (https://github/zhufengpeixun/zhufeng_automation.git) //模塊的git倉庫,選填。npm的用戶一般都使用github做為自己的git倉庫
keywords: node.js gulp //在npmjs官網(wǎng)搜索時的關鍵字
author: zhangrenyang //項目作者名字
license: (ISC) MIT //授權協(xié)議
About to write to D:\mygit\zhufeng_automation\package.json:
{
"name": "learngulp",
"version": "1.0.0",
"description": "learn gulp",
"main": "index.js",
"dependencies": {
"gulp": "^3.9.0"
},
"devDependencies": {},
"scripts": {
"test": "test.js"
},
"repository": {
"type": "git",
"url": "https://git.coding.net/zhufengpeixun/zhufeng_automation.git"
},
"keywords": [
"node.js",
"gulp"
],
"author": "zhangrenyang",
"license": "MIT"
}
Is this ok? (yes) yes //對以上內容確認無誤后,就可以直接回車確認了
回車后會在當前目錄下創(chuàng)建一個 package.json 文件
這樣可以把 gulp 作為項目的開發(fā)依賴(只在開發(fā)時用,不會發(fā)布到線上),通過
npm install gulp --save-dev
在node_modules下安裝本地的gulp庫并把添加配置到 package.json 文件里面。
"devDependencies": {
"gulp": "^3.9.0"
}
1.創(chuàng)建配置文件:
gulp 的任務要放到一個叫 gulpfile.js 的文件里面,先在項目的根目錄下面創(chuàng)建一個這樣的文件。 然后在這個文件的頂部添加下面這行代碼:
var gulp = require('gulp');
通過require可以把gulp模塊引入當前項目并賦值給gulp變量
這樣,gulp 這個變量里面就會擁有 gulp 的所有的方法了
2.創(chuàng)建gulp的任務
可以使用gulp的task方法
同樣我們去創(chuàng)建一個叫 hello 的任務,它要做的事就是在控制臺上輸出 "您好" 這兩個字
第一個參數(shù)是任務的名稱,第二個參數(shù)是任務的定義,是一個匿名函數(shù)
gulp.task('hello', function () {
console.log('您好');
});
執(zhí)行 Gulp 的任務,打開命令行工具,進入到項目所在的目錄,然后輸入:
gulp hello
會返回:
$ gulp hello
[21:36:34] Using gulpfile D:\mygit\zhufeng_automation\gulpfile.js
[21:36:34] Starting 'hello'...
您好
[21:36:34] Finished 'hello' after 959 μs
gulp后面跟著的是任務的名稱,不輸入任務名稱的話會默認找default任務,找不到會報錯
執(zhí)行其它任務
可以使用
gulp <task> <othertask>
gulp 只有你需要熟知的參數(shù)標記,其他所有的參數(shù)標記只在一些任務需要的時候使用。
- -v 或 --version 會顯示全局和項目本地所安裝的 gulp 版本號
- --gulpfile 手動指定一個 gulpfile 的路徑,這在你有很多個 gulpfile 的時候很有用。這也會將 CWD 設置到該 gulpfile 所在目錄
- --cwd dirpath 手動指定 CWD。定義 gulpfile 查找的位置,此外,所有的相應的依賴(require)會從這里開始計算相對路徑
- -T 或 --tasks 會顯示所指定 gulpfile 的 task 依賴樹
- --tasks-simple 會以純文本的方式顯示所載入的 gulpfile 中的 task 列表
- --color 強制 gulp 和 gulp 插件顯示顏色,即便沒有顏色支持
- --no-color 強制不顯示顏色,即便檢測到有顏色支持
- --silent 禁止所有的 gulp 日志
gulp.js工作方式
gulp的使用流程一般是:首先通過gulp.src()方法獲取到想要處理的文件流,
然后把文件流通過pipe方法導入到gulp的插件中,
最后把經(jīng)過插件處理后的流再通過pipe方法導入到gulp.dest()中,
gulp.dest()方法則把流中的內容寫入到文件中。例如:
var gulp = require('gulp');
gulp.src('script/src.js') // 獲取文件的流的api
.pipe(gulp.dest('dist/dest.js')); // 寫文件的api
使用gulp,僅需知道4個API即可:gulp.task(),gulp.src(),gulp.dest(),gulp.watch(),所以很容易就能掌握
gulp.src()
在Gulp中,使用的是Nodejs中的stream(流),首先獲取到需要的stream,然后可以通過stream的pipe()方法把流導入到你想要的地方,比如Gulp的插件中,經(jīng)過插件處理后的流又可以繼續(xù)導入到其他插件中,當然也可以把流寫入到文件中。所以Gulp是以stream為媒介的,它不需要頻繁的生成臨時文件,這也是Gulp的速度比Grunt快的一個原因。再回到正題上來,gulp.src()方法正是用來獲取流的,但要注意這個流里的內容不是原始的文件流,而是一個虛擬文件對象流(Vinyl files),這個虛擬文件對象中存儲著原始文件的路徑、文件名、內容等信息,這個我們暫時不用去深入理解,你只需簡單的理解可以用這個方法來讀取你需要操作的文件就行了。其語法為:
gulp.src(globs[, options])
globs參數(shù)是文件匹配模式(類似正則表達式),用來匹配文件路徑(包括文件名),當然這里也可以直接指定某個具體的文件路徑。當有多個匹配模式時,該參數(shù)可以為一個數(shù)組。
options為可選參數(shù)。通常情況下我們不需要用到
glob語法
gulp內部使用了node-glob模塊來實現(xiàn)其文件匹配功能。我們可以使用下面這些特殊的字符來匹配我們想要的文件:
[圖片上傳失敗...(image-131e3-1531969756686)]
下面以例子來加深理解
glob匹配
gulp.dest()
gulp.dest()方法是用來寫文件的,其語法為:
gulp.dest(path[,options])
path為寫入文件的路徑
options為一個可選的參數(shù)對象,通常我們不需要用到
要想使用好gulp.dest()這個方法,就要理解給它傳入的路徑參數(shù)與最終生成的文件的關系。
gulp的使用流程一般是這樣子的:首先通過gulp.src()方法獲取到我們想要處理的文件流,
然后把文件流通過pipe方法導入到gulp的插件中,最后把經(jīng)過插件處理后的流再通過pipe方法導入到gulp.dest()中,
gulp.dest()方法則把流中的內容寫入到文件中,
這里首先需要弄清楚的一點是,我們給gulp.dest()傳入的路徑參數(shù),只能用來指定要生成的文件的目錄,
而不能指定生成文件的文件名,它生成文件的文件名使用的是導入到它的文件流自身的文件名,
所以生成的文件名是由導入到它的文件流決定的,即使我們給它傳入一個帶有文件名的路徑參數(shù),
然后它也會把這個文件名當做是目錄名,例如:
var gulp = require('gulp');
gulp.src('script/jquery.js')
.pipe(gulp.dest('dist/foo.js'));
//最終生成的文件路徑為 dist/foo.js/jquery.js,而不是dist/foo.js
要想改變文件名,可以使用插件 gulp-rename
下面說說生成的文件路徑與我們給gulp.dest()方法傳入的路徑參數(shù)之間的關系。
gulp.dest(path)生成的文件路徑是我們傳入的path參數(shù)后面再加上gulp.src()中有通配符開始出現(xiàn)的那部分路徑。例如:
var gulp = reruire('gulp');
//有通配符開始出現(xiàn)的那部分路徑為 `**/*.js`
gulp.src('script/**/*.js')
.pipe(gulp.dest('dist')); //最后生成的文件路徑為 dist/**/*.js
//如果 **/*.js 匹配到的文件為 jquery/jquery.js ,則生成的文件路徑為 dist/jquery/jquery.js
再舉更多一點的例子
gulp.src('script/avalon/avalon.js') //沒有通配符出現(xiàn)的情況
.pipe(gulp.dest('dist')); //最后生成的文件路徑為 dist/avalon.js
//有通配符開始出現(xiàn)的那部分路徑為 **/underscore.js
gulp.src('script/**/underscore.js')
//假設匹配到的文件為script/util/underscore.js
.pipe(gulp.dest('dist')); //則最后生成的文件路徑為 dist/util/underscore.js
gulp.src('script/*') //有通配符出現(xiàn)的那部分路徑為 *
//假設匹配到的文件為script/zepto.js
.pipe(gulp.dest('dist')); //則最后生成的文件路徑為 dist/zepto.js
通過指定gulp.src()方法配置參數(shù)中的base屬性,我們可以更靈活的來改變gulp.dest()生成的文件路徑。
當我們沒有在gulp.src()方法中配置base屬性時,base的默認值為通配符開始出現(xiàn)之前那部分路徑,例如:
gulp.src('app/src/**/*.css') //此時base的值為 app/src
上面我們說的gulp.dest()所生成的文件路徑的規(guī)則,其實也可以理解成,用我們給gulp.dest()傳入的路徑替換掉gulp.src()中的base路徑,最終得到生成文件的路徑。
gulp.src('app/src/**/*.css') //此時base的值為app/src,也就是說它的base路徑為app/src
//設該模式匹配到了文件 app/src/css/normal.css
.pipe(gulp.dest('dist')) //用dist替換掉base路徑,最終得到 dist/css/normal.css
所以改變base路徑后,gulp.dest()生成的文件路徑也會改變
gulp.src(script/lib/*.js) //沒有配置base參數(shù),此時默認的base路徑為script/lib
//假設匹配到的文件為script/lib/jquery.js
.pipe(gulp.dest('build')) //生成的文件路徑為 build/jquery.js
gulp.src(script/lib/*.js, {base:'script'}) //配置了base參數(shù),此時base路徑為script
//假設匹配到的文件為script/lib/jquery.js
.pipe(gulp.dest('build')) //此時生成的文件路徑為 build/lib/jquery.js
用gulp.dest()把文件流寫入文件后,文件流仍然可以繼續(xù)使用。
gulp.task()
gulp.task方法用來定義任務,其語法為:
gulp.task(name[, deps], fn)
name 為任務名
deps 是當前定義的任務需要依賴的其他任務,為一個數(shù)組。當前定義的任務會在所有依賴的任務執(zhí)行完畢后才開始執(zhí)行。如果沒有依賴,則可省略這個參數(shù)
fn 為任務函數(shù),我們把任務要執(zhí)行的代碼都寫在里面。該參數(shù)也是可選的。
gulp.task('mytask', ['array', 'of', 'task', 'names'], function() { //定義一個有依賴的任務
// Do something
});
gulp.task()這個API沒什么好講的,但需要知道執(zhí)行多個任務時怎么來控制任務執(zhí)行的順序。
gulp中執(zhí)行多個任務,可以通過任務依賴來實現(xiàn)。例如我想要執(zhí)行one,two,three這三個任務,那我們就可以定義一個空的任務,然后把那三個任務當做這個空的任務的依賴就行了:
//只要執(zhí)行default任務,就相當于把one,two,three這三個任務執(zhí)行了
gulp.task('default',['one','two','three']);
如果任務相互之間沒有依賴,任務會按你書寫的順序來執(zhí)行,如果有依賴的話則會先執(zhí)行依賴的任務。
但是如果某個任務所依賴的任務是異步的,就要注意了,gulp并不會等待那個所依賴的異步任務完成,而是會接著執(zhí)行后續(xù)的任務。例如:
gulp.task('one',function(){
//one是一個異步執(zhí)行的任務
setTimeout(function(){
console.log('one is done')
},5000);
});
//two任務雖然依賴于one任務,但并不會等到one任務中的異步操作完成后再執(zhí)行
gulp.task('two',['one'],function(){
console.log('two is done');
});
上面的例子中我們執(zhí)行two任務時,會先執(zhí)行one任務,但不會去等待one任務中的異步操作完成后再執(zhí)行two任務,而是緊接著執(zhí)行two任務。所以two任務會在one任務中的異步操作完成之前就執(zhí)行了。
那如果我們想等待異步任務中的異步操作完成后再執(zhí)行后續(xù)的任務,該怎么做呢?
有三種方法可以實現(xiàn):
第一:在異步操作完成后執(zhí)行一個回調函數(shù)來通知gulp這個異步任務已經(jīng)完成,這個回調函數(shù)就是任務函數(shù)的第一個參數(shù)。
gulp.task('one',function(cb){ //cb為任務函數(shù)提供的回調,用來通知任務已經(jīng)完成
//one是一個異步執(zhí)行的任務
setTimeout(function(){
console.log('one is done');
cb(); //執(zhí)行回調,表示這個異步任務已經(jīng)完成
},5000);
});
//這時two任務會在one任務中的異步操作完成后再執(zhí)行
gulp.task('two',['one'],function(){
console.log('two is done');
});
第二:定義任務時返回一個流對象。適用于任務就是操作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對象,例如
var Q = require('q'); //一個著名的異步處理的庫 https://github.com/kriskowal/q
gulp.task('one',function(cb){
var deferred = Q.defer();
// 做一些異步操作
setTimeout(function() {
deferred.resolve();
}, 5000);
return deferred.promise;
});
gulp.task('two',['one'],function(){
console.log('two is done');
});
gulp.task()就這些了,主要是要知道當依賴是異步任務時的處理。
gulp.watch()
gulp.watch()用來監(jiān)視文件的變化,當文件發(fā)生變化后,我們可以利用它來執(zhí)行相應的任務,例如文件壓縮等。其語法為
gulp.watch(glob[, opts], tasks)
glob 為要監(jiān)視的文件匹配模式,規(guī)則和用法與gulp.src()方法中的 glob 相同。
opts 為一個可選的配置對象,通常不需要用到
tasks 為文件變化后要執(zhí)行的任務,為一個數(shù)組
gulp.task('uglify',function(){
//do something
});
gulp.task('reload',function(){
//do something
});
gulp.watch('js/**/*.js', ['uglify','reload']);
gulp.watch()還有另外一種使用方式:
gulp.watch(glob[, opts, cb])
glob和 opts 參數(shù)與第一種用法相同
cb參數(shù)為一個函數(shù)。每當監(jiān)視的文件發(fā)生變化時,就會調用這個函數(shù),并且會給它傳入一個對象,該對象包含了文件變化的一些信息,type屬性為變化的類型,可以是 added , changed , deleted ; path 屬性為發(fā)生變化的文件的路徑
gulp.watch('js/**/*.js', function(event){
console.log(event.type); //變化類型 added為新增,deleted為刪除,changed為改變
console.log(event.path); //變化的文件的路徑
});
1. 導入gulp
打開 gulpfile.js ,在這里先去創(chuàng)建一個對象,叫 gulp ,讓它等于 require('gulp');
這樣這個 gulp 對象就擁有了 gulp 提供的所有屬性還有方法了。
2. 創(chuàng)建源文件
mkdir app
在app下創(chuàng)建 index.html
3. 任務目標
然后用 gulp 的 task 方法,去創(chuàng)建一個任務,
這個任務要做的事就是把我們項目里的app下的index.html 這個文件,復制到一個叫 dist 的目錄里面,這個 dist 目錄表示的是 distribution,也就是正式發(fā)新版。
4. 編寫任務
- 先給這個任務起個名字 ... 可以叫它 copy-html
- 再寫一個匿名函數(shù)
- 先用寫 return
- 大部分的 gulp 任務,首先要做的就是去讀取要處理的文件,讀取文件用的是 src 這個方法,在這個方法里,指定一下要讀取的文件 index.html
找到要處理的文件以后,再用一個 pipe方法,你可以把這個 pipe 想像成是一個管道, 把文件讀取進來,放到一個管道里,在這個管道里面,你可以使用 gulp 的插件去處理讀取進來的文件
因為這里我們只是簡單的把文件保存到一個指定的地方,所以不需要使用插件,可以使用 gulp 的 dest 這個方法,在這個方法里,指定一下文件要存儲到的那個位置。
這樣我們就創(chuàng)建好了這個把單個文件復制到指定位置的任務
5. 執(zhí)行
打開命令行工具
先確定當前的位置是在項目的目錄里面
然后輸入 gulp+后面加上任務的名字
gulp copy-html
輸入回車,會出現(xiàn)一些提示:
- 使用的 gulpfile 的位置
- 開始執(zhí)行的任務
- 還有任務結束所花的時間
代碼
var gulp = require('gulp');
gulp.task('copy-html',function(){
return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});
1. 導入gulp
打開 gulpfile.js ,在這里先去創(chuàng)建一個對象,叫 gulp ,讓它等于 require('gulp');
這樣這個 gulp 對象就擁有了 gulp 提供的所有屬性和方法了。
2. 創(chuàng)建源文件
在app下創(chuàng)建
[圖片上傳失敗...(image-b235d5-1531969756685)]
3. 任務目標
然后用gulp的task方法,去創(chuàng)建一個任務,
把imgs目錄里的文件復制到dist這個目錄的下面
4. 編寫任務
- 先給這個任務起個名字 ... 可以叫它 copy-imgs
- 再寫一個匿名函數(shù)
- 先寫 return
- 大部分的 gulp 任務,首先要做的就是去讀取要處理的文件,讀取文件用的是 src 這個方法
'app/imgs/*.png' 指app/imgs/這個目錄里面的所有的.png格式的圖片,這個 * 號表示的就是任何東西. *.png 意思就是,不管圖片的文件名是什么,只要它是 .png 格式的就行.
gulp.src('app/imgs/*.png')
5. 執(zhí)行
打開命令行工具
先確定當前的位置是在項目的目錄里面
然后輸入 gulp+后面加上任務的名字
gulp copy-imgs
輸入回車,會出現(xiàn)一些提示:
- 使用的 gulpfile 的位置
- 開始執(zhí)行的任務
- 還有任務結束所花的時間
完成以后,你會看到,在項目的dist這個目錄里面,會創(chuàng)建一個叫imgs的目錄,在這個目錄里面,有兩張圖片1.png 2.png它們都是從項目根目錄下的imgs這個目錄里面復制過來的.
在這個目錄里面,這張jpg格式的圖片,還有small里面的圖片,并沒有復制到dist下面的 imgs 目錄里面。因為我們寫的glob只匹配imgs目錄下的所有的.png格式的圖片
6.指定多個后綴
如果你想把 imgs 目錄下面的所有的圖像文件都復制到 dist 下面的 imgs 目錄里面,在這個 src 方法的 glob 里面,可以指定多個擴展名,現(xiàn)在是 *.png, 后面加上一組花括號,在這個花括號里面,指定多個擴展名.{jpg,png}注意逗號的后面不要使用空格.
多個glob
有些任務你可能需要用到多個glob,這樣我們就可以用一個數(shù)組,數(shù)組里的每個項目表示的就是用來匹配文件的glob。
比如我們的項目里有兩個目錄,css還有js。
每個目錄下面都有一些文件。
我們想創(chuàng)建一個任務,需要用到這兩個目錄里面的東西。
在這個任務里,我們就可以使用多個glob。
['app/css/*.css','app/js/*.js']
數(shù)組里有兩個glob
再次執(zhí)行任務
會發(fā)現(xiàn)glob中的文件都拷貝到dist下面去了
排除特定文件
在 glob 的前面,再加上一個!號,表示這是要排除掉的文件
['app/css/*.css','app/js/*.js','!app/js/*.tmp.js']
代碼
var gulp = require('gulp');
/**
* 復制圖片
*/
gulp.task('copy-images',function(){
return gulp.src('app/imgs/*.jpg').pipe(gulp.dest('dist'));
});
/**
* 1\. {} 里可以指定多個擴展名
* 2\. * 匹配所有的字符,除了路徑分隔符 /
* 3\. ** 匹配所有的字符,包括路徑分隔符 /
*/
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}').pipe(gulp.dest('dist'));
});
/**
* 匹配多個目錄 glob
* 可以填寫一個數(shù)組
*
*/
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js'],{base:'app'}).pipe(gulp.dest('dist'));
});
/**
* 匹配多個目錄 glob
* ! 排除一個文件
*
*/
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js','!app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});
1. 組合任務
在創(chuàng)建 gulp 任務的時候,我們可以去給任務指定它依賴的其它的任務。
比如,這里我們創(chuàng)建了三個任務,copy-html,copy-imgs,copy-other。
我們想再創(chuàng)建一個叫 build 的任務,這個任務依賴這里的這三個任務。
2. 編寫
使用gulp的task這個方法去創(chuàng)建任務
先給這個任務起個名字,叫做 build.
再把這個方法的第二個參數(shù)設置成一個數(shù)組,這個數(shù)組里的項目就是這個任務所依賴的任務,輸入一組方括號,再把它需要的三個任務,作為這個數(shù)組的三個項目.
我們可以繼續(xù)去設計這個任務要作的事情,用一個匿名函數(shù),
可以讓它在控制臺上輸出 編譯成功 ,這樣在執(zhí)行 build 任務的時候,會先去執(zhí)行它依賴的三個任務,最后再執(zhí)行它本身要做的任務。
3. 執(zhí)行
保存,打開命令行工具,輸入 gulp build,回車.
注意這里會同時去執(zhí)行 build 需要的三個任務,并不是先執(zhí)行一個,等待完成以后再去執(zhí)行一個,
這些依賴的任務是同時執(zhí)行的,等它們都完成以后,才會執(zhí)行 build 本身要做的任務,這里就是在控制臺上,輸出編譯成功 這幾個字兒。
代碼
var gulp = require('gulp');
gulp.task('copy-html',function(){
return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}').pipe(gulp.dest('dist'));
});
/**
* 匹配多個目錄 glob
* ! 排除一個文件
*
*/
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});
gulp.task('default',['copy-html','copy-images','copy-other'],function(){
console.log('全部拷貝任務執(zhí)行完畢!');
});
1. 監(jiān)聽任務
使用 gulp 的 watch 這個方法,我們可以去監(jiān)視一些文件,當這些文件發(fā)生變化的時候,立即去執(zhí)行一些指定的任務
2.編寫
先打開 gulpfile.js,再去創(chuàng)建一個任務
gulp.task,這個任務可以叫做 watch,再用一個匿名函數(shù),在它里面,再用 gulp 的 watch 方法去做點事情。
輸入 gulp.watch(),先指定一下要監(jiān)視的文件,比如去監(jiān)視 index.html
再把要執(zhí)行的任務列表放到這里,這個任務列表要放到一個數(shù)組里,所以先輸入一組方括號,要執(zhí)行的任務是 copy-html.
它的意思就是,我們在執(zhí)行 watch 任務的時候,去監(jiān)視 index.html 這個文件的變化,當這個文件發(fā)生變化以后,就去自動執(zhí)行 copy-html 這個任務。
執(zhí)行
保存 回到命令行工具
先去執(zhí)行一下剛才創(chuàng)建的 watch 這個任務 gulp watch ,這樣 gulp 就會去監(jiān)視文件的變化了,你會看到這個任務并沒有立即結束,它會一直運行,直到我們手工退出這個任務,退出可以按一上 ctrl + C
再回到項目,打開 index.html 這個文件,隨便修改一個地方,然后保存一下,回到命令行,你會看到 gulp 執(zhí)行了 copy-html 這個任務,因為 index.html 這個文件發(fā)生了變化
每次保存被監(jiān)視的文件,都會去執(zhí)行指定的任務列表。
回到項目,打開 dist 下面的 index.html,你會看到修改之后的 index.html 已經(jīng)被復制到了這個目錄的下面.
代碼
var gulp = require('gulp');
gulp.task('copy-html',function(){
return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}',{base:'app'}).pipe(gulp.dest('dist'));
});
/**
* 匹配多個目錄 glob
* ! 排除一個文件
*
*/
gulp.task('copy-other',function(){
return gulp.src(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});
//在執(zhí)行watch的時候會監(jiān)控index.html文件的變化,發(fā)生變化后可以執(zhí)行拷貝html的任務
gulp.task('default',function(){
gulp.watch('app/index.html',['copy-html']);
gulp.watch('app/imgs/**/*.{jpg,png}',['copy-images']);
gulp.watch(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],['copy-other']);
});
gulp插件
gulp提供了一些很實用的接口,但本身并不能做太多的事情。
可以讀取文件、寫入文件以及監(jiān)控文件等一少部分功能。
其它實用的功能都是依靠插件來進行擴展的。
這些插件可以實現(xiàn)比如
- 編譯 Sass:gulp-sass
- 編譯 Less:gulp-less
- 合并文件:gulp-concat
- 壓縮js 文件:gulp-uglify
- 重命名js文件:gulp-rename
- 優(yōu)化圖像大小:gulp-imagemin
- 壓縮css 文件:gulp-minify-css
- 創(chuàng)建本地服務器:gulp-connect
- 實時預覽 gulp-connect
插件列表
使用插件
1. npm install xxx --save-dev 安裝插件
2. 在 **gulpfile.js** 頂部引入此插件
3. 在創(chuàng)建任務的時候使用此插件
自動加載gulp 插件
gulp-load-plugins這個插件能自動幫你加載package.json文件里的gulp插件。
例如假設你的package.json文件里的依賴是這樣的:
"devDependencies": {
"gulp": "^3.9.0",
"gulp-concat": "^2.6.0",
"gulp-connect": "^2.2.0",
"gulp-imagemin": "^2.3.0",
}
然后我們可以在gulpfile.js中使用gulp-load-plugins來幫我們加載插件:
var gulp = require('gulp');
//加載gulp-load-plugins插件,并馬上運行它
var $ = require('gulp-load-plugins')();
然后我們要使用gulp-rename和gulp-ruby-sass這兩個插件的時候,
就可以使用.concat和.connect來代替了,也就是原始插件名去掉gulp-前綴,之后再轉換為駝峰命名。
less
less插件可以把less文件編譯成css
less任務
可以在app/less下面創(chuàng)建文件page.less,然后就可以把此文件編譯到dist下面
安裝插件
npm install gulp-less --save-dev
安裝后可以在node-modules里看到此插件
也可以在package.json的devDependencies里面看到此插件的配置
代碼如下
var gulp = require('gulp');
var less = require('gulp-less');
gulp.task('less',function(){
return gulp.src('app/less/*.less').pipe(less()).pipe(gulp.dest('dist/css'));
});
gulp.task('default',['less']);
sass
想要使用 Gulp 去把 Sass 編譯成 CSS ,我們可以使用 gulp-sass 這個插件。
插件任務
可以在app/sass下面創(chuàng)建文件base.scss,然后就可以把此文件編譯到dist下面
安裝插件
npm install gulp-sass --save-dev
安裝后可以在node-modules里看到此插件
也可以在package.json的devDependencies里面看到此插件的配置 "gulp-sass": "^2.0.4"
使用插件
在項目里面,app/sass 這個目錄的下面,有一個sass文件,就是這個base.scss
$blue : #1875e7;
div {
color : $blue;
}
下面,我們可以使用gulp-sass這個插件,把這個目錄里面的sass文件編譯成css ,
再放到 dist 目錄下面的 css 這個目錄的下面。
代碼如下
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('sass',function(){
return gulp.src('app/sass/*.scss').pipe(sass()).pipe(gulp.dest('dist/css'));
});
gulp.task('default',['sass']);
gulp-connect
有些時候我們需要把文件放到本地服務器上去預覽,gulp-connect可以幫我們創(chuàng)建一個本地服務器去運行我們的項目
安裝插件
npm install gulp-connect --save-dev
加上一個 --save-dev,把這個插件放到開發(fā)依賴里面。
創(chuàng)建任務
打開 gulpfile.js
先在文件的頂部這里
去包含一下這個 gulp-connect 插件
給它起個名字connect ...
var connect = require('gulp-connect');
代碼如下
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('server',function(){
connect.server({
root:'dist',//服務器的根目錄
port:8080 //服務器的地址,沒有此配置項默認也是 8080
});
});
gulp.task('default',['server']); //運行此任務的時候會在8080上啟動服務器,
gulp-connect
我們希望當文件變化的時候瀏覽器可以自動刷新,這樣我們就不需要文件修改后手動去刷新瀏覽器了
代碼如下
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('copy-html',function(){
gulp.src('app/index.html')//指定源文件
.pipe(gulp.dest('dist'))//拷貝到dist目錄
.pipe(connect.reload());//通知瀏覽器重啟
});
gulp.task('watch',function(){
gulp.watch('app/index.html',['copy-html']);//當index.html文件變化時執(zhí)行copy-html任務
});
gulp.task('server',function(){
connect.server({
root:'dist',//服務器的根目錄
port:8080, //服務器的地址,沒有此配置項默認也是 8080
livereload:true//啟用實時刷新的功能
});
});
gulp.task('default',['server','watch']);//運行此任務的時候會在8080上啟動服務器,
gulp-concat
這個插件可以把幾個文件合并到一塊
安裝
npm install gulp-concat --save-dev
代碼如下
var gulp = require('gulp');
var concat = require('gulp-concat');
gulp.task('concat',function(){
return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])//指定要合并的文件glob
.pipe(concat('app.js'))//進行合并并指定合并后的文件名
.pipe(gulp.dest('dist/js'));//輸出到目標路徑
});
gulp.task('default',['concat']);
gulp-concat
合并后我們可以對JS文件進行合并,最小化處理
安裝
先打開命令行安裝
npm install gulp-uglify --save-dev
代碼如下
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify')
gulp.task('uglify',function(){
return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])
.pipe(concat('app.js')) //把多個JS文件合并成一個文件
.pipe(uglify()) //對合并后的app.js文件進行壓縮
.pipe(gulp.dest('dist/js')); //輸出到目的地
});
gulp.task('default',['uglify']);
html文件壓縮
gulp-minify-html插件用來壓縮html文件。
代碼如下
var gulp = require('gulp'),
minifyHtml = require("gulp-minify-html");
gulp.task('minify-html', function () {
gulp.src('src/*.html') // 要壓縮的html文件
.pipe(minifyHtml()) //壓縮
.pipe(gulp.dest('dist/html'));//輸出到目的地
});
gulp-rename
在把處理好的文件存放到指定的位置之前,我們可以先去重新命名一下它。可以使用gulp-rename這個插件.
安裝
npm install gulp-rename --save-dev
代碼如下
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
gulp.task('uglify',function(){
return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])//指定要處理的文件
.pipe(concat('app.js'))//合并成一個文件
.pipe(gulp.dest('dist/js'))//保存此文件
.pipe(uglify())//進行壓縮
.pipe(rename('app.min.js'))//對此文件進行重命名
.pipe(gulp.dest('dist/js'));//再輸出一次
});
gulp.task('default',['uglify']);
gulp-minify-css
如果要想壓縮css,我們可以使用gulp-minify-css
安裝
npm install gulp-minify-css --save-dev
代碼如下
var gulp = require('gulp');
var less = require('gulp-less');
var minify = require('gulp-minify-css');//在文件的頂部去包含這個插件,起個名字,叫做 minify
var rename = require('gulp-rename');
gulp.task('minify',function(){
return gulp.src('app/less/page.less')//指定 less文件
.pipe(less())//把less編譯成css
.pipe(gulp.dest('dist/css'))//輸出到目的地
.pipe(minify())//對 css再進行壓縮
.pipe(rename('page.min.css'))//重命名
.pipe(gulp.dest('dist/css'));//輸出到目的地
});
gulp.task('default',['less']);
gulp-imagemin
如果要想在保證不改變圖像質量的情況下,讓圖像文件的體積變得更小一點,我們可以使用gulp-imagemin
安裝
npm install gulp-imagemin --save-dev
代碼如下
var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
gulp.task('copy-images',function(){
return gulp.src('app/imgs/**/*.{jpg,png}')//指定要壓縮的圖片
.pipe(imagemin()) //進行圖片壓縮
.pipe(gulp.dest('dist'));//輸出目的地
});
gulp.task('default',['copy-images']);
jshint
可以用此插件進行代碼檢查
安裝
npm install gulp-jshint --save-dev
代碼
var gulp = require('gulp'),
jshint = require("gulp-jshint");
gulp.task('jsLint', function () {
gulp.src('src/*.js')
.pipe(jshint()) //進行代碼檢查
.pipe(jshint.reporter()); // 輸出檢查結果
});
DEMO :
{
"name": "tongbanke",
"version": "1.0.0",
"description": "tobanke'",
"main": "main.js",
"scripts": {
"test": "test"
},
"repository": {
"type": "git",
"url": "gulp"
},
"keywords": [
"gulp",
"test"
],
"author": "kongzhi",
"license": "ISC",
"devDependencies": {
"gulp": "^3.6.2",
"gulp-coffee": "^1.4.2",
"gulp-concat": "^2.6.0",
"gulp-connect": "^2.3.1",
"gulp-jshint": "^2.0.4",
"gulp-less": "^3.1.0",
"gulp-obfuscate": "^0.2.9",
"gulp-uglify": "^2.0.0",
"gulp-watch": "^0.6.2",
"jshint": "^2.9.3"
}
}
var gulp = require('gulp');
var concat = require('gulp-concat'); //文件合并
var uglify = require('gulp-uglify'); //文件壓縮
var rename = require('gulp-rename'); //文件重命名
var obfuscate = require('gulp-obfuscate'); //代碼混淆
var connect = require('gulp-connect'); //創(chuàng)建一個本地服務器
jshint = require("gulp-jshint"); //語法校驗
// 語法檢查
gulp.task('jshint', function() {
console.log('語法檢查...');
return gulp.src('src/*.js')
.pipe(jshint()) //進行代碼檢查
.pipe(jshint.reporter('default')); // 輸出檢查結果
});
//創(chuàng)建一個本地服務器
gulp.task('server',function(){
console.log("創(chuàng)建本地服務器!")
connect.server({
livereload:true,//啟用實時刷新的功能
root:'./',//服務器的根目錄
port:12306 //服務器的地址,沒有此配置項默認也是 8080
});
});
// 合并文件之后壓縮代碼
gulp.task('minify', function() {
console.log('壓縮合并');
return gulp.src('src/*.js') //指定要合并的文件glob
.pipe(concat('main.js')) //進行合并并指定合并后的文件名
.pipe(gulp.dest('min.js')) //輸出到目標路徑
.pipe(uglify())
.pipe(rename('main.min.js'))
.pipe(connect.reload()) //通知瀏覽器重啟
.pipe(gulp.dest('min.js'));
});
// 監(jiān)視文件的變化
gulp.task('watch', function() {
console.log('文件有變動');
gulp.watch('src/*.js', ['minify','jshint'],function(event){
console.log(event.type); //變化類型 added為新增,deleted為刪除,changed為改變
console.log(event.path); //變化的文件的路徑
});
});
// 注冊默認任務
gulp.task('default', ['minify', 'watch','server', 'jshint'], function() {
console.log('壓縮合并混淆重命名');
return gulp.src('main.min.js')
.pipe(obfuscate()); //壓縮完代碼混淆
});