代碼同步
browser-sync 使用方法
browser-sync-spa
gulp-livereload 實時刷新
AngularJS
eslint-plugin-angular
gulp-angular-filesort
結合使用以gulp-inject正確的順序注入您的AngularJS應用程序文件(腳本),以擺脫所有Uncaught Error: [$injector:modulerr]。為了正確工作,每個角度文件需要具有唯一命名的模塊和setter語法(帶括號),即angular.module('myModule', [])。
gulp-angular-templatecache 將html模板緩存到$templateCache中
gulp-ng-annotate //是一個處理angularjs依賴注入的插件,它的用法如下
gulp.task('build-app-js', function () {
return gulp.src('src/app/**/*.js')
.pipe(ngAnnotate({single_quotes: true}))
.pipe(gulp.dest(buildDir + '/js/app'));
});
正常我們寫angular代碼是這樣子的
angular.module('app', [])
.controller('AppCtrl', ['$scope', function($scope) {
// 別的代碼
}])
但使用了這個插件之后,每一個依賴注入的項就不用再寫兩遍了,如
angular.module('app', [])
.controller('AppCtrl', function($scope) {
// 別的代碼
})
gulp-ng-annotate會幫我們生成帶中括號的寫法 ,這樣子是不是節(jié)省了很多重復工作呢?尤其是在注入的服務非常多的時候,可以少寫很多代碼,并且也不用擔心順序有沒有寫錯。
文件操作
gulp-filter 過濾文件
Example:https://github.com/hjzheng/CUF_meeting_knowledge_share/blob/master/2015-11-10/gulpfile.js
gulp-filter可以把stream里的文件根據(jù)一定的規(guī)則進行篩選過濾。比如gulp.src中傳入匹配符匹配了很多文件,可以把這些文件pipe給gulp-filter作二次篩選,如gulp.src('/.js').pipe($.filter(/a/.js)),本來選中了所有子文件下的js文件,經(jīng)過篩選后變成名為a的子文件夾下的js文件。那有人要問了,為什么不直接將需要的篩選傳入gulp.src,干嘛要多篩選一步呢?這里面有兩種情況:
gulp.src與$.filter中間可能需要別的處理,比如我對所有文件做了操作1以后,還需要篩選出一部分做操作2。
第二種情況就要談到gulp-filter的另外一個特性:篩選之后還可以restore回去。比如我對所有文件做了操作1,篩選了一部分做操作2,最后要把所有的文件都拷貝到最終的位置。代碼如下:
var filter = $.filter('**/a/*.js');
gulp.src('**/*.js')
.pipe(action1())
.pipe(filter)
.pipe(action2())
.pipe(filter.restore())
.pipe(gulp.dest('dist'))
可以看到,如果沒有restore這個操作,那么拷貝到最終位置的文件將只包含被過濾出來的文件,這樣一restore,所有的文件都被拷貝了。
gulp-flatten 當拷貝文件時,不想拷貝目錄時使用
例子:https://segmentfault.com/q/1010000004266922
gulp-flatten非常實用,可能知道別的庫中flatten函數(shù)的同學已經(jīng)猜到它是干嘛的了。比如gulp.src('*/.js')匹配了很多文件,包括a/b/c.js,d/e.js,f/g/h/i/j/k.js,l.js,這些文件的層級都不一樣,一旦我們將這個文件pipe給$.flatten(),則所有的文件夾層級都會去掉,最終的文件將是c.js,e.js,k.js,l.js,在一些場景下還是非常有用的。
JS/CSS自動注入
gulp-replace
gulp-rev 把靜態(tài)文件名改成hash的形式。
gulp-rev-append 給頁面引用的靜態(tài)文件增加hash后綴,避免被瀏覽器緩存
效果如下:
"/css/base.css" => "/dist/css/base.css?v=1d87bebe"
"/js/mod.js" => "/dist/mod.js?v=61e0be79"
"/images/bg.png" => "/images/bg.png?v=35c3af8134"
gulp-rev-replace 配合 gulp-rev 使用,拿到生成的 manifest。json 后替換對應的文件名稱。
gulp-useref 與 gulp-rev、gulp-rev-replace
這三個工具之所以放在一起講,是因為它們一般都是一起使用的。它們要解決什么問題呢?通過上面的wiredep也好,gulp-inject也好,插入了一堆JS、CSS文件到HTML中,一旦部署到生產(chǎn)環(huán)境,這么多文件必然是要合并壓縮的。光是壓縮還不夠,為了解決緩存問題,每次合并壓縮后要給最終的文件加hash,這樣每次文件內容一變動,hash也會跟著變動,就不存在瀏覽器依然使用緩存的老文件的問題。這樣得到最終的文件以后,肯定還要將這個文件替換回HTML中去,一大堆的script和link標簽替換成最終合并壓縮帶hash的版本。
前面啰啰嗦嗦的一大堆工作就是這三個插件要解決的問題了。首先,gulp-useref根據(jù)注釋將HTML中需要合并壓縮的區(qū)塊找出來,對區(qū)塊內的所有文件進行合并。注意:它只負責合并,不負責壓縮!所以合并出來的文件我們要自行壓縮,壓縮以后調用gulp-rev負責在文件名后追加hash。最后調用gulp-rev-replace負責把最終的文件名替換回HTML中去。扯了大半天,還是直接上例子吧。先來看看HTML中的注釋:
<!-- build:css static/styles/lib.css -->
<!-- bower:css -->
<!-- endbower -->
<!-- endbuild -->
<!-- build:css static/styles/app.css -->
<!-- inject:css -->
<!-- endinject -->
<!-- endbuild -->
<!-- build:js static/js/lib.js -->
<!-- bower:js -->
<!-- endbower -->
<!-- endbuild -->
<!-- build:js static/js/app.js -->
<!-- inject:js -->
<!-- endinject -->
<!-- endbuild -->
gulp-useref識別的就是build開頭的注釋,build后面首先跟的是類型擴展名,然后后面的路徑就是build區(qū)塊中的所有文件進行合并后的文件路徑,這個相對路徑是相對于這個HTML的路徑。上面的例子中我們用build區(qū)塊把bower和inject進來的文件包起來,這些文件就可以被gulp-useref合并了。再來看gulp中useref相關task的定義:
var assets = $.useref.assets({searchPath: 'app/src/'});
var cssFilter = $.filter('**/*.css');
var jsAppFilter = $.filter('**/app.js');
var jslibFilter = $.filter('**/lib.js');
return gulp
.src('index.html')
.pipe(assets)
.pipe(cssFilter)
.pipe($.csso())
.pipe(cssFilter.restore())
.pipe(jsAppFilter)
.pipe($.uglify())
.pipe(getHeader())
.pipe(jsAppFilter.restore())
.pipe(jslibFilter)
.pipe($.uglify())
.pipe(jslibFilter.restore())
.pipe($.rev())
.pipe(assets.restore())
.pipe($.useref())
.pipe($.revReplace())
.pipe(gulp.dest('dist'));
首先一上來,先調用$.useref.assets()函數(shù),這個函數(shù)返回一個stream,包含已經(jīng)合并后的文件。可以嘗試在第9行后面加上前面介紹過的gulp-print插件.pipe($.print()),打印出stream里的文件,發(fā)現(xiàn)就是前面HTML中4個build注釋塊后面的4個文件。注意這里調用的時候跟了一個searchPath的參數(shù),它的用處就是指定從哪個路徑開始尋找build區(qū)塊底下的文件。比如build區(qū)塊底下有這么一行<script src="static/js/a.js"></script>,那最終gulp-useref將從這個路徑app/src/static/js/a.js找到這個文件。第3到5行定義了3個filter,這主要是為了后面壓縮準備的。下面正式看stream的pipe流程。先選出要處理的HTML文件,然后調用剛才得到的assets得到合并后的4個文件,第10到12行篩選出合并后的CSS文件進行壓縮(壓縮類插件下篇文章再講),第13到16行篩選出app.js進行壓縮,第17到19行篩選出lib.js進行壓縮。之所以要區(qū)別對待app.js和lib.js,是因為app.js是我們自己寫的代碼,壓縮后要加上header(第15行,使用前面介紹過的gulp-header插件),而lib.js是第三方的各種庫,直接壓縮即可。后面調用gulp-rev給壓縮后的4個文件加hash,然后調用assets.restore()將src源換回HTML文件,這是為了后面調用$.useref(),因為$.useref()做替換的src源是HTML文件,同樣后面調用gulp-rev-replace將帶hash的文件替換回HTML,它要求的src源也必須是HTML文件。這里的順序很重要,因為這幾個插件接受的源不一樣,gulp-rev接受的是JS、CSS文件,而gulp-useref和gulp-rev-replace接受的是HTML。還有一個問題:gulp-rev-replace是怎么知道gulp-rev進行hash前后的文件名對應關系呢?其實gulp-rev會生成一個manifest的文件,內容是類似下面的JSON:
{
"static/styles/lib.css": "static/styles/lib-d41d8cd98f.css"
"static/js/lib.js": "static/js/lib-273c2cin3f.js"
}
當然這個文件默認是不會生成在文件系統(tǒng)里的,可以通過.pipe($.rev.manifest())將這個文件保存到本地。有了這個文件,gulp-rev-replace甚至可以脫離gulp-rev獨立工作哦!
gulp-inject //文件的注入
個人理解: 就是把 css,js全部利用這個插件添加到 index.html 頁面里,不需要手動去添加
<script src="../bower_components/jquery/dist/jquery.js"></script>
<link src="css/index.css"/>
<!-- inject:js -->
<script src="scripts/app.js"></script>
<!-- endinject -->
壓縮
gulp-zip
gulp-mini-css 壓縮css使用的
gulp-mini-html
gulp-useref 用uglify壓縮js
url:https://www.npmjs.com/package/gulp-useref
說到優(yōu)化的時候,我們需要想到:壓縮,拼接。也就是減少體積和HTTP次數(shù)。
開發(fā)者面臨的主要問題是很難按照正確的順序合并文件。
<body>
<!-- other stuff -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
</body>
由于文件路徑的的不同,使用 https://www.npmjs.com/package/gulp-concat
等插件非常困難。
慶幸的是, gulp-useref
解決了這個問題。
gulp-useref
會將多個文件拼接成單一文件,并輸出到相應目錄。
<!-- build:<type> <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
可以是js,css,或者remove。如果你設為remove,Gulp將不會生成文件。
指定產(chǎn)出路徑。
我們想最終產(chǎn)出main.min.js。可以這樣寫:
<!--build:js js/main.min.js -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->
gulp-uglify //壓縮、混淆js文件用的
基本使用
var gulp = require('gulp'),
uglify = require('gulp-uglify');
gulp.task('jsmin', function () {
gulp.src('src/js/index.js')
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
壓縮多個js文件
var gulp = require('gulp'),
uglify = require('gulp-uglify');
gulp.task('jsmin', function () {
gulp.src(['src/js/index.js','src/js/detail.js']) //多個文件以數(shù)組形式傳入
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
匹配符“!”,“”,“*”,“{}”
var gulp = require('gulp'),
uglify= require('gulp-uglify');
gulp.task('jsmin', function () {
//壓縮src/js目錄下的所有js文件
//除了test1.js和test2.js(**匹配src/js的0個或多個子文件夾)
gulp.src(['src/js/*.js', '!src/js/**/{test1,test2}.js'])
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
指定變量名不混淆改變
var gulp = require('gulp'),
uglify= require('gulp-uglify');
gulp.task('jsmin', function () {
gulp.src(['src/js/*.js', '!src/js/**/{test1,test2}.js'])
.pipe(uglify({
//mangle: true,//類型:Boolean 默認:true 是否修改變量名
mangle: {except: ['require' ,'exports' ,'module' ,'$']}//排除混淆關鍵字
}))
.pipe(gulp.dest('dist/js'));
});
gulp-uglify其他參數(shù) 具體參看
var gulp = require('gulp'),
uglify= require('gulp-uglify');
gulp.task('jsmin', function () {
gulp.src(['src/js/*.js', '!src/js/**/{test1,test2}.js'])
.pipe(uglify({
mangle: true,//類型:Boolean 默認:true 是否修改變量名
compress: true,//類型:Boolean 默認:true 是否完全壓縮
preserveComments: 'all' //保留所有注釋
}))
.pipe(gulp.dest('dist/js'));
});
gulp-css-base64
把小圖片的URL替換為Base64編碼圖片。
gulp-imagemin 壓縮圖片
壓縮圖片文件(包括PNG、JPEG、GIF和SVG圖片)
github:https://github.com/sindresorhus/gulp-imagemin
基本使用
var gulp = require('gulp'),
imagemin = require('gulp-imagemin');
gulp.task('testImagemin', function () {
gulp.src('src/img/*.{png,jpg,gif,ico}')
.pipe(imagemin())
.pipe(gulp.dest('dist/img'));
});
gulp-imagemin其他參數(shù) 具體參看
var gulp = require('gulp'),
imagemin = require('gulp-imagemin');
gulp.task('testImagemin', function () {
gulp.src('src/img/*.{png,jpg,gif,ico}')
.pipe(imagemin({
optimizationLevel: 5, //類型:Number 默認:3 取值范圍:0-7(優(yōu)化等級)
progressive: true, //類型:Boolean 默認:false 無損壓縮jpg圖片
interlaced: true, //類型:Boolean 默認:false 隔行掃描gif進行渲染
multipass: true //類型:Boolean 默認:false 多次優(yōu)化svg直到完全優(yōu)化
}))
.pipe(gulp.dest('dist/img'));
});
深度壓縮圖片
var gulp = require('gulp'),
imagemin = require('gulp-imagemin'),
//確保本地已安裝imagemin-pngquant [cnpm install imagemin-pngquant --save-dev]
pngquant = require('imagemin-pngquant');
gulp.task('testImagemin', function () {
gulp.src('src/img/*.{png,jpg,gif,ico}')
.pipe(imagemin({
progressive: true,
svgoPlugins: [{removeViewBox: false}],//不要移除svg的viewbox屬性
use: [pngquant()] //使用pngquant深度壓縮png圖片的imagemin插件
}))
.pipe(gulp.dest('dist/img'));
});
只壓縮修改的圖片。
壓縮圖片時比較耗時,在很多情況下我們只修改了某些圖片,沒有必要壓縮所有圖片,使用”gulp-cache”只壓縮修改的圖片,沒有修改的圖片直接從緩存文件讀取(C:\Users\Administrator\AppData\Local\Temp\gulp-cache)。
var gulp = require('gulp'),
imagemin = require('gulp-imagemin'),
pngquant = require('imagemin-pngquant'),
//確保本地已安裝gulp-cache [cnpm install gulp-cache --save-dev]
cache = require('gulp-cache');
gulp.task('testImagemin', function () {
gulp.src('src/img/*.{png,jpg,gif,ico}')
.pipe(cache(imagemin({
progressive: true,
svgoPlugins: [{removeViewBox: false}],
use: [pngquant()]
})))
.pipe(gulp.dest('dist/img'));
});
注意:它只負責合并,不負責壓縮
編譯
gulp-sass 編譯sass用的
gulp-sourcemaps 編譯sass時生成額外的.map文件用的
代碼分析
gulp-eslint
工具
gulp-load-plugins 模塊化管理。可以加載package.json文件中所有的gulp模塊
gulp-autoprefixer 自動添加css前綴
基本用法
var gulp = require('gulp'),
autoprefixer = require('gulp-autoprefixer');
gulp.task('testAutoFx', function () {
gulp.src('src/css/index.css')
.pipe(autoprefixer({
browsers: ['last 2 versions', 'Android >= 4.0'],
cascade: true, //是否美化屬性值 默認:true 像這樣:
//-webkit-transform: rotate(45deg);
// transform: rotate(45deg);
remove:true //是否去掉不必要的前綴 默認:true
}))
.pipe(gulp.dest('dist/css'));
});
gulp-autoprefixer的browsers參數(shù)詳解
- last 2 versions: 主流瀏覽器的最新兩個版本
- last 1 Chrome versions: 谷歌瀏覽器的最新版本
- last 2 Explorer versions: IE的最新兩個版本
- last 3 Safari versions: 蘋果瀏覽器最新三個版本
- Firefox >= 20: 火狐瀏覽器的版本大于或等于20
- iOS 7: IOS7版本
- Firefox ESR: 最新ESR版本的火狐
- 5%: 全球統(tǒng)計有超過5%的使用率
gulp-gh-pages 使用gulp來把markdown生成html文檔并上傳到git pages上
chalk
del 清除文件
gulp-plumber
gulp 的錯誤處理有點坑,假如發(fā)生錯誤進程就掛了。相對的解決辦法不少,但是這個是我個人比較推薦的,比特么在容易出錯的地方寫錯誤監(jiān)聽靠譜。所以這個插件可以阻止 gulp 插件發(fā)生錯誤導致進程退出并輸出錯誤日志。
estraverse 遍歷函數(shù)
gulp-prompt 將交互式控制臺提示添加到gulp
gulp-protractor
gulp-rename 修改文件名稱。比如有時我們需要把app.js改成app.min.js,瞬間高級了
gulp-shell
gulp-size 顯示您的項目的規(guī)模
gulp-util
gulp-util帶有很多方便的函數(shù),其中最常用的應該就是log了。$.util.log()支持傳入多個參數(shù),打印結果會將多個參數(shù)用空格連接起來。它與console.log的區(qū)別就是所有$.util.log的結果會自動帶上時間前綴。另外,它還支持顏色,如$.util.log($.util.colors.magenta('123'));打印出來的123是品紅色的。其實$.util.colors就是一個 chalk的實例,而chalk是專門用來處理命令行打印著色的一個工具。
http-proxy-middleware
lodash
main-bower-files
uglify-save-license
wiredep
wiredep就是wire dependence的意思,它的作用就是把bower.json中聲明的dependence自動的包含到HTML中去。
要插入文件,wiredep需要解決兩個問題:
插入的位置:wiredep通過識別HTML中的注釋來識別插入位置,如
<!-- bower:css -->
<!-- endbower -->
<!-- bower:js -->
<!-- endbower -->
不同類型的文件被插入到不同的區(qū)塊。
插入什么文件:要插入的文件列表自然來自bower.json,每個bower安裝的依賴庫,根目錄下邊都有一個自己的bower.json文件,其中的main字段指明了使用這個庫需要包含的文件,wiredep最終包含的文件列表就來自這個字段。有些情況下,庫自身的bower.json的main字段可能會多包含文件或少包含文件,如果想要定制這個列表,則可以在自己的bower.json中使用overrides字段,如下面的代碼覆蓋了mdi這個庫的main字段。
"overrides": {
"mdi": {
"main": [
"css/materialdesignicons.css"
]
}
},
wiredep插件支持很多參數(shù),常用的主要有兩個:
bowerJson:指定bower.json的內容,注意這個字段不是bower.json文件的位置,這個參數(shù)需要使用require后的結果賦值:require('bower.json')。
directory:指定存放bower安裝后的依賴包的路徑,通常是bower_components。注意最終插入到HTML中的文件列表的路徑是index.html文件相對于本文件夾的相對路徑。
使用wiredep也比較簡單,直接把它傳入到stream中即可,如gulp.src('index.html').pipe(wiredep(options))。
gulp-order 對src中的文件按照指定順序進行排序
本地整理,留作備份。