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/) 我們可以根據自己的需求,來需要某個模組,註冊任務和執行還是上面一樣的。