Gulp.js----比Grunt更易用的前端構建工具
Grunt一直是前端構建工具,然而他也不是毫無缺陷的,gulp的作者 Eric Schoffstall 在他介紹 gulp.js 的 presentation 中總結了 Grunt 的幾點不足之處:
- 插件很難遵守單一職責。因為 Grunt 的 API 設計缺憾,使得許多插件不得不負責一些和其主要任務無關的事情。比如說要對處理后的文件進行更名操作,你可能使用的是
uglify插件,也有可能使用的是concat插件(取決於工作流的最后一個環節是誰)。 - 用插件做一些本來不需要插件來做的事情。因為 Grunt 提供了統一的 CLI 入口,子任務由插件定義,由 CLI 命令來調用執行,因此哪怕是很簡單的外部命令(比如說運行
karma start)都得有一個插件來負責封裝它,然后再變成 Grunt CLI 命令的參數來運行,多此一舉。 - 試圖用配置文件完成所有事,結果就是混亂不堪。規模較大,構建/分發/部署流程較為復雜的項目,其
Gruntfile有多龐雜相信有經歷的人都有所體會。而 gulp.js 奉行的是“寫程序而不是寫配置”,它走的是一種 node way。 - 落后的流程控制產生了讓人頭痛的臨時文件/文件夾所導致的性能滯后。這是 gulp.js 下刀子的重點,也是本標題里“流式構建”所解決的根本問題。流式構建改變了底層的流程控制,大大提高了構建工作的效率和性能,給用戶的直觀感覺就是:更快。
Gulp相對於Grunt有五大優勢:
1. 使用 gulp.js,你的構建腳本是代碼,而不是配置文件;
2. 使用標准庫(node.js standard library)來編寫腳本;
3. 插件都很簡單,只負責完成一件事.
4. 任務都以最大的並發數來執行;
5. 輸入/輸出(I/O)是基於“流式”的。
下面我們先來看看在項目中如何使用Gulp來構建項目的吧!在構建之前,我們先來安裝下Gulp。
一:Gulp安裝-命令行工具。全局安裝gulp 命令:npm install -g gulp 如下:

如上,說明gulp已經安裝完成!
二:項目demo演示
1. 進入項目gulp的根目錄下,如下所示:

如上,是我項目gulp文件。
1. 在項目的根目錄下看有沒有package.json,如果沒有的話,我們需要運行下命令 npm init, 如下所示:

之后在項目跟路徑下生產package.json文件.
2. 在項目文件gulp下安裝為開發的依賴組件,運行命令:npm install --save-dev gulp 如下所示:

運行完成后,在根目錄下生產node_modules文件,如下所示:

3. 在項目的跟路徑下新建Gulpfile.js,如下所示:

我們可以給Gulpfile.js的初始內容為:
var gulp = require('gulp');
gulp.task('default', function () {});
4. 運行gulp命令,如下所示:

上面是最基本的運行操作,下面我們來看一個具體的demo吧,還是如上的項目gulp文件,我們現在的需求是想把gulp項目文件下的src所有js文件合並到dist目錄下的build.js,壓縮后的文件為build-min.js。
在這之前,我們需要安裝如下插件:
1. 語法檢查(gulp-jshint).
2. 合並文件(gulp-concat).
3. 壓縮代碼(gulp-uglify).
一:語法檢查 運行命令:npm install gulp-jshint --save-dev 如下圖所示:

二:合並文件 運行命令:npm install gulp-concat --save-dev 如下圖所示:

三:壓縮代碼 運行命令:npm install gulp-uglify --save-dev 如下圖所示:

插件裝完成后,我們可以看看根目錄下多了幾個插件,如下所示:

其中gulp-rename我們去掉,不要的。
四:在項目的根目錄下創建Gulpfile.js文件,內容如下:
var gulp = require('gulp'); var jshint = require('gulp-jshint'); var concat = require('gulp-concat'); var uglify = require('gulp-uglify'); // 語法檢查 gulp.task('jshint', function () { return gulp.src('src/*.js') .pipe(jshint()) .pipe(jshint.reporter('default')); }); // 合並文件之后壓縮代碼 gulp.task('minify', function (){ return gulp.src('src/*.js') .pipe(concat('build.js')) .pipe(gulp.dest('dist')) .pipe(uglify()) .pipe(rename('build.min.js')) .pipe(gulp.dest('dist')); }); // 監視文件的變化 gulp.task('watch', function () { gulp.watch('src/*.js', ['jshint', 'minify']); }); // 注冊缺省任務 gulp.task('default', ['jshint', 'minify', 'watch']);
最后在命令行下,運行gulp命令即可。如下所示:

現在我們回到目錄下,可以看到如下所示:

如上Gulpfile.js,我們可以看到,基本上所有的任務都是這個模式。
gulp.task(“任務名稱”,function(){
return gulp.src(“文件”)
.pie(…)
.pie(….)
})
獲取要處理的文件,傳遞給下一個環節處理,然后把返回的結果繼續傳給下一個環節,直到所有環節結束,pipe就是stream模塊里負責傳遞流數據的方法而已。
下面我們來看看gulp簡單的API,如下:
1. gulp.task(name[,deps],fn) 注冊任務。
name: 是任務名稱,deps是可選的數組,列出需要在本任務運行要執行的任務,fn是任務體,這是gulp.js的核心,比如下面是非常簡單的任務函數:
gulp.task(“test”,function(){console.log(“111”)});
task方法還可以指定按順序運行的一組任務,如下:
gulp.task(“build”,[‘css’,’js’,’java’]);
上面的代碼先指定build任務,它按次序有css,js,java三個任務組成,注意:每個任務都是異步調用,所以沒有辦法保證是那個任務先執行完。
如果希望要按照嚴格的順序執行完,可以如下寫代碼:
gulp.task(‘css’,[‘js’],function(){});
如上代碼表明:css的任務依賴於js,所以css一定會在js運行完成后在執行。
如果一個任務名字為default,它表示默認任務,在命令行中直接運行gulp即可。
gulp.task(‘default’,function(){});
2.gulp.src(globs[,options]):指明源文件的路徑,options是可選的。
有以下幾種形式:
1.js/app.js 指明確切的文件名。
2.js/*.js 某個目錄所有后綴名為js的文件。
3.js/**/*.js 某個目錄及其所有子目錄中的所有后綴名為js的文件。
4.!js/app.js 除了js/app.js以外的所有文件
5. *.+(js|css) 匹配項目的根目錄下,所有后綴名為js或css的文件。
Src方法的參數還可以是一個數組,用來指定多個成員,如下:
gulp.src([‘js/**/*.js’,!js/app.js]).
3. gulp.dest(path) 指明任務處理后的目標輸出路徑。
4.gulp.watch(globs[,options],task)/gulp.watch(globs[,options,cb]),監聽文件的變化並運行相應的任務。
如上gulpfile.js代碼,我監聽了jshint及minify代碼,只要語法錯誤就會在命令行給出提示:如下所示:

官網有更多的關於gulp插件(http://gratimax.net/search-gulp-plugins/) 我們可以根據自己的需求,來需要某個模塊,注冊任務和執行還是上面一樣的。
