因為之前一直有人給我推薦gulp,說他這裡好哪裡好的。實際上對我來說夠用就行。grunt熟悉以後實際上他的配置也不難,說到效率的話如果真是要完整打包上線也不在乎那麼幾秒時間,對於項目來說線上效率關鍵,但是線下效率只要不是讓人無法忍受頁沒有太多問題。不過不管怎麼說,需要親自用過gulp之後才能品評他和 ...
因為之前一直有人給我推薦gulp,說他這裡好哪裡好的。實際上對我來說夠用就行。grunt熟悉以後實際上他的配置也不難,說到效率的話如果真是要完整打包上線也不在乎那麼幾秒時間,對於項目來說線上效率關鍵,但是線下效率只要不是讓人無法忍受頁沒有太多問題。不過不管怎麼說,需要親自用過gulp之後才能品評他和grunt之間的優劣。不廢話,直接上實例。
本人自建了一個前端目錄結構,後續的例子都是以這個目錄結構為準。dest是我們打包壓縮結果保存目錄,現在是空的。以後每完成一個實例,我們就會清空一下dest目錄,保證下一個實例的結果和實例代碼對應。
1. 第一個簡單的gulp打包
1)需要安裝nodejs:http://www.cnblogs.com/chuaWeb/p/nodejs-npm.html
本人的nodejs工程目錄為F:\chuaNodejs(後續所有相對路徑都是相對於這個目錄)
2) 創建package.json文件,可以使用npm init命令來創建。然後在其中的devDependencies中包含gulp相關的插件依賴。我的package.json是這樣的
1 { 2 "name": "my-gulp", 3 "version": "1.0.0", 4 "description": "demo", 5 "dependencies": { 6 "express": "3.x" 7 }, 8 "devDependencies": { 9 "gulp-clean": "^0.3.2", 10 "gulp": "^3.9.1", 11 "gulp-concat": "^2.6.0", 12 "gulp-mini-css": "^0.0.3", 13 "gulp-uglify": "^1.5.3", 14 "gulp-requirejs-optimize": "^0.3.2" 15 }, 16 "scripts": { 17 "test": "echo \"Error: no test specified\" && exit 1" 18 }, 19 "author": "chua", 20 "license": "ISC" 21 }
隨著我們使用npm安裝的插件添加,裡面的內容隨之更改。
命令行到nodejs目錄(需要系統管理員許可權,不然後續過程中會報錯)安裝gulp作為項目的開發依賴(devDependencies,當然也可以用其他方式安裝):npm install --save-dev gulp
gulp有很多官方插件可以去查看安裝:http://gulpjs.com/plugins/。
但是下麵的幾個插件基本上都要用到,可以先安裝
gulp:這個是必須安裝的,沒有它,其它組件都用不了(註意watch組件直接集成在gulp中了,無需額外安裝watch組件)
gulp-mini-css :壓縮css使用的
gulp-uglify:壓縮、混淆js文件用的
3) 在nodejs工程目錄下建一個gulpfile.js,內容為
1 var gulp = require('gulp'), 2 mincss = require('gulp-mini-css'), 3 uglify = require('gulp-uglify'); 4 5 var src_css = './src/css', 6 dest_css = './dest/css', 7 src_js = './src/js', 8 dest_js = './dest/js'; 9 10 gulp.task('mincss', function () { 11 gulp.src(src_css+'/**/*.css') 12 .pipe(mincss()) 13 .pipe(gulp.dest(dest_css)); 14 }); 15 16 gulp.task('minjs', function () { 17 gulp.src(src_js+'/**/*.js') 18 .pipe(uglify()) 19 .pipe(gulp.dest(dest_js)); 20 }); 21 22 gulp.task('watch', function () { 23 gulp.watch(src_css+'/**/*.css',['mincss']); 24 gulp.watch(src_js+'/**/*.js',['minjs']); 25 }); 26 27 gulp.task('default',function(){ 28 gulp.run('minjs','mincss'); 29 gulp.run('watch'); 30 });
可以看到裡面和nodejs代碼寫法類似。
4)命令行運行:gulp
執行結果
可以看到我們將src的js/css都壓縮打包到了對應的dest文件夾下
註意:gulp命令和gulp default等價。而且這個時候監聽任務是一直執行著的,每當有相應的文件改動那麼就會執行相應的任務。
5)源碼分析:
1 //註冊一個叫做mincss的任務,命令行gulp mincss可以運行這個任務 2 //需要說明的是代碼中”*”代表的是一層文件,而”**”代表要遞歸其子文件夾 3 gulp.task('mincss', function () { 4 gulp.src(src_css+'/**/*.css')//返回了src/css/下的全部(包含子文件夾里的).css文件流;gulp.src(str)返回了一個可讀的stream 5 .pipe(mincss())//執行gulp-mini-css組件任務,壓縮所有css文件流 6 .pipe(gulp.dest(dest_css));//將文件流寫入到 COMPRESS/css 里的對應路徑下;gulp.dest(str)返回一個可寫的stream 7 });
1 //註冊名為watch的任務 2 gulp.task('watch', function () { 3 gulp.watch(src_css+'/**/*.css',['mincss']);//監聽src/css/下的全部.css文件,若有改動則執行名為'mincss'任務 4 gulp.watch(src_js+'/**/*.js',['minjs']);//監聽src/css/下的全部.js文件,若有改動則執行名為'minjs'任務 5 });
1 //每個gulpfile.js里都應當有一個dafault任務,它是預設任務入口,運行gulp的時候實際只是調用該任務(從而來調用其它的任務) 2 gulp.task('default',function(){ 3 gulp.run('minjs','mincss');//立刻執行'minjs','mincss'這兩個任務;gulp.run(tasks)表示運行對應的任務 4 gulp.run('watch');//立刻執行'watch'任務 5 });
比較grunt而言,確實更容易上手。
2. 合併壓縮
有些時候為了減少請求需要合併多個文件,且需要壓縮。使用uglify和concat即可做到這一點。所以還要下載concat插件:npm install gulp-concat --save-dev
gulpfile.js代碼
1 var gulp = require('gulp'), 2 uglify = require('gulp-uglify'), 3 concat = require('gulp-concat'); 4 5 var src_js = './src/js', 6 dest_js = './dest/js'; 7 8 gulp.task('minjs', function () { 9 gulp.src(src_js+'/**/*.js') 10 .pipe(uglify())//壓縮 11 .pipe(concat("all.min.js"))//合併 12 .pipe(gulp.dest(dest_js)); 13 }); 14 15 gulp.task('watch', function () { 16 gulp.watch(src_js+'/**/*.js',['minjs']);//監聽src/css/下的全部.js文件,若有改動則執行名為'minjs'任務 17 }); 18 19 gulp.task('default',['minjs','watch']);
這裡文件會壓縮的順序按照字母順序並層層深入的順序壓縮到all.min.js中。
這裡我們看到gulp.task的用法有多種,gulp.task(name[, deps], fn),deps是一個包含任務列表的數組,這些任務會在你當前任務運行之前完成。詳情參考:http://www.gulpjs.com.cn/docs/api/
如果要按照指定的順序壓縮的話,你需要為gulp.src執行文件列表才行,gulp會按照文件列表數組中元素的順序壓縮。
gulpfile.js源碼
1 var gulp = require('gulp'), 2 uglify = require('gulp-uglify'), 3 concat = require('gulp-concat'); 4 5 var src_js = './src/js', 6 dest_js = './dest/js'; 7 8 gulp.task('minjs', function () { 9 gulp.src([src_js+'/bootstrap.min.js',src_js+'/jquery.js'])//先壓縮bootstrap,然後再壓縮jquery 10 .pipe(uglify()) 11 .pipe(concat("all.min.js")) 12 .pipe(gulp.dest(dest_js)); 13 }); 14 15 gulp.task('watch', function () { 16 gulp.watch(src_js+'/**/*.js',['minjs']);//監聽src/css/下的全部.js文件,若有改動則執行名為'minjs'任務 17 }); 18 19 gulp.task('default',['minjs','watch']);
3. watch事件監聽
watch組件包含在gulp中,不許另行下載。
我們在最開始的實例中已經用過了watch的基本用法:gulp.watch(glob,tasks)
現在來看一下另一種用法:gulp.watch(glob,callback)
gulpfile.js源碼
1 var gulp = require('gulp'), 2 uglify = require('gulp-uglify'), 3 notify = require("gulp-notify"); 4 5 gulp.task('minjs', function () { 6 gulp.src('src/main.js') 7 .pipe(uglify()) 8 .pipe(gulp.dest("dest/")); 9 }); 10 11 gulp.task('watch', function () { 12 gulp.watch('src/main.js',function(e){ 13 //e有兩個屬性type/path 14 if(e.type == "changed"){//added, changed, or deleted 15 gulp.run("minjs"); 16 console.log(e.type + ": " + e.path); 17 } 18 }); 19 }); 20 21 gulp.task('default',["minjs",'watch']);
可以看到函數的參數(事件)e有兩個屬性type和path。我們可以根據他們的值去做一些定製服務。
Gulp.watch()的另一個非常好的特性是返回watcher對象。利用watcher來監聽額外的事件或者向watch中添加文件。
來看另一份gulpfile.js代碼
1 var gulp = require('gulp'), 2 uglify = require('gulp-uglify'), 3 notify = require("gulp-notify"); 4 5 gulp.task('minjs', function () { 6 gulp.src('src/main.js') 7 .pipe(uglify()) 8 .pipe(gulp.dest("dest/")); 9 }); 10 11 gulp.task('watch', function () { 12 var watcher = gulp.watch('src/main.js',["minjs"]); 13 watcher.on('change',function(e){ 14 if(e.type == "changed"){ 15 console.log(e.type + ": " + e.path); 16 } 17 }); 18 }); 19 20 gulp.task('default',["minjs",'watch']);
除了change事件,還可以監聽很多其他的事件:
end 在watcher結束時觸發(這意味著,在文件改變的時候,任務或者回調不會執行)
error 在出現error時觸發
ready 在文件被找到並正被監聽時觸發
nomatch 在glob沒有匹配到任何文件時觸發
Watcher對象也包含了一些可以調用的方法:
watcher.end() 停止watcher(以便停止執行後面的任務或者回調函數)
watcher.files() 返回watcher監聽的文件列表
watcher.add(glob) 將與指定glob相匹配的文件添加到watcher(也接受可選的回調當第二個參數)
watcher.remove(filepath) 從watcher中移除個別文件
4. 一些gulp重要的插件
gulp:這個是必須安裝的,沒有它,其它組件都用不了(註意watch組件直接集成在gulp中了,無需額外安裝watch組件)
gulp-mini-css :壓縮css使用的
gulp-uglify:壓縮、混淆js文件用的
gulp-clean:清空文件夾
1 gulp.src(globs) 2 .pipe(clean());
gulp-clean-css:壓縮css文件(原gulp-minify-css捨棄)
1 gulp.src('src/css/t1.css') 2 .pipe(cssmin()) 3 .pipe(gulp.dest("dest/css/"));
gulp-less:將less文件編譯成css
1 gulp.src('src/css/t.less') 2 .pipe(less()) 3 .pipe(gulp.dest("dest/css/"))
gulp-notify:加控制台描述
1 gulp.src("./src/test.ext") 2 .pipe(notify("Found file: <%= file.relative %>!"));
gulp-autoprefixer:自動為css樣式添加相容瀏覽器的首碼
1 gulp.src('src/css/t1.css') 2 .pipe(autoprefixer({ 3 browsers: ['last 2 versions', 'Android >= 4.0'], 4 cascade: true, //是否美化屬性值 預設:true 像這樣: 5 //-webkit-transform: rotate(45deg); 6 // transform: rotate(45deg); 7 remove:true //是否去掉不必要的首碼 預設:true 8 })) 9 .pipe(gulp.dest('dist/css'));
gulp-template://替換變數以及動態html
src/greeting.html
<h1>Hello <%= name %></h1>
gulpfile.js
處理
1 gulp.src('src/greeting.html') 2 .pipe(template({name: 'Sindre'})) 3 .pipe(gulp.dest('dist'))
gulp-rename: //更改名稱
1 gulp.src('src/css/**/*.css') 2 .pipe(concat('all.css')) 3 .pipe(gulp.dest('dest/css/')) 4 .pipe(rename({ suffix: '.min' }))//添加尾碼 5 .pipe(gulp.dest('dest/css'));
gulp-if: 邏輯判斷
1 gulp.task('cssmin', function () { 2 gulp.src('src/css/**/*.css') 3 .pipe(concat('all.css')) 4 .pipe(cssmin()) 5 .pipe(gulp.dest('dest/css')); 6 }); 7 gulp.task('main', function () { 8 gulp.src('src/css/**/*.css') 9 .pipe(gif(true,cssmin())) 10 .pipe(gulp.dest('dest/css')); 11 });
del: 刪除指定文件
del('dest/css/**/*.css')
gulp-htmlmin: 壓縮html
1 gulp.src('src/html/*.html') 2 .pipe(htmlmin()) 3 .pipe(gulp.dest('dist/html'));
gulp-jshint : 檢查js
1 gulp.src('src/js/*.js') 2 .pipe(jshint());
browser-sync: 這個實際不算是gulp的一個插件,但是他實現了在發現文件被修改時會實時更新網頁的功能,很有意思,有興趣的童鞋可以研究一下
gulp-connect:在本地啟動一個Web Server。一般來說寫前端界面代碼時想要調試都需要一個伺服器,這個伺服器解決了以往後端伺服器的問題。
1 var gulp = require('gulp'), 2 connect = require('gulp-connect'); 3 4 gulp.task('connect', function() { 5 connect.server(); 6 }); 7 8 gulp.task('default', ['connect']);
更多詳情可以參考https://www.npmjs.com/package/gulp-connect
使用實例可以參考使用Gulp構建本地開發Web伺服器
5. 總結
從速度來說:gulp比grunt要快,gulp不用重覆讀寫文件。特別是對於項目很大的情況,使用gulp打包確實是更好的選擇。
從使用簡潔方面來說:grunt需要的配置文件,在一些時候配置文件會很多,而gulp是按任務分解的,所有的配置變成了一連串的任務,從代碼上面來說可能會比grunt簡潔一些。
從學習成本來說:別人說gulp學習成本比grunt低,但是就本人而言,實際上兩者都很容易上手,基礎的都很簡單,更詳細的需要查官網,所以應該是差不多的。
從成熟程度來說:grunt要比gulp成熟,grunt的插件雖然有些私人寫的導致良莠不齊,但是數量和完備性要比gulp好,甚至很多怪癖的需求都能找到相關的插件。而且一般來說越是簡潔的東西約不適合大型項目,gulp等待檢驗。所以對於大型項目建議使用成熟的grunt。
現在來說的話,gulp的功能也是比較完備的了,基本構建都不成問題,所以對於中小型項目,按照做程式員就一定用最好的工具的標準的話,比較推薦gulp。
gulp因為是基於流的構建,而且這個流是vinyl流,和buffer不相容,參考這篇文章http://sentsin.com/web/210.html
gulp的一些技巧參考http://www.gulpjs.com.cn/docs/recipes/
如果覺得本文不錯,請點擊右下方【推薦】!