1、優點

1.1 易於使用

通過程式碼優於配置的策略,gulp讓簡單的任務簡單,複雜的任務可管理

1.2 構建快速

利用node.js流的威力,你可以快速構建專案並減少頻繁的IO操作

1.3 外掛高質

gulp嚴格的外掛指南確保外掛如你期望的那樣簡潔高質的工作

1.4 易於學習

通過最少的API,掌握gulp毫不費力,構建工作盡在掌握:如同一系列流管道

2、gulp使用說明

2.1 安裝

在工程根目錄下進入cmd

初始化npm,在專案根目錄下新建package.json檔案

npm init

全域性環境下安裝 gulp,且儲存到package.json中

npm install gulp -g --save-dev
npm install module-name -save 自動把模組和版本號新增到dependencies部分
npm install module-name -save-dev 自動把模組和版本號新增到devdependencies部分

2.2 配置gulpfile.js

在專案根目錄下建立一個gulpfile.js檔案,並進行相關配置

詳細的方法說明後面會提到

2.2.1 引入gulp外掛
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
jshint = require('gulp-jshint'),
concat = require('gulp-concat'),
watch = require('gulp-watch'),
clean = require('gulp-clean'),
minifycss = require('gulp-minify-css'),
prefixAndSuffix = require('gulp-prefix-suffix');
2.2.2 合併壓縮js
//合併JS檔案到build/all.min.js
gulp.task('combine', function(){
return gulp.src(['src/**/*.js','!src/lib/**/*.js','!src/app.js','!src/main.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(concat('all.min.js'))
.pipe(prefixAndSuffix("define(['app'], function(app){","});"))
.pipe(uglify())
.pipe(gulp.dest('build'));
});
2.2.3 合併壓縮css
//合併JS檔案到build/all.min.js
gulp.task('combine', function(){
return gulp.src(['src/**/*.js','!src/lib/**/*.js','!src/app.js','!src/main.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(concat('all.min.js'))
.pipe(prefixAndSuffix("define(['app'], function(app){","});"))
.pipe(uglify())
.pipe(gulp.dest('build'));
});
2.2.4 壓縮圖片
//合併壓縮CSS檔案
gulp.task('css', function(){
return gulp.src(['src/**/*.css','!src/lib/**/*.css'])
.pipe(concat('all.min.css'))
.pipe(minifycss())
.pipe(gulp.dest('build'));
});
2.2.4 壓縮圖片
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true }))
.pipe(gulp.dest('dist/assets/img'))
.pipe(notify({ message: 'Images task complete' })); });
optimizationLevel設定為3表示對所有來源的image進行壓縮處理,設定位5表示僅對新的或者有改動的image進行壓縮
2.2.5 清空build
//清空build
gulp.task('clean', function(){
return gulp.src('build')
.pipe(clean());
});
2.2.6 拷貝檔案

對於沒有進行壓縮的html和lib中引用的第三方外掛或庫框架和壓縮合並好的js,css,image等檔案,要從開發目錄拷貝到工程執行目錄

//拷貝html、圖片等到build
gulp.task('copyOther', function(){
return gulp.src(['src/**/*','!src/**/*.js'])
.pipe(gulp.dest('build'));
});
//拷貝lib資料夾
gulp.task('copyLib', function(){
return gulp.src('src/lib/**/*.js')
.pipe(gulp.dest('build/lib'));
});
//拷貝app.js和main.js
gulp.task('copyJs', function(){
return gulp.src(['src/app.js','src/main.js'])
.pipe(gulp.dest('build'));
});
2.2.7 檔案改動監控
gulp.task('watch', function(){
gulp.watch('src/**/*',['default']);
})

2.3 gulp模組方法說明

gulp.task(name[, deps], fn) 定義任務 name:任務名稱 deps:依賴任務名稱 fn:回撥函式 
gulp.run(tasks...):儘可能多的並行執行多個task 
gulp.watch(glob, fn):當glob內容發生改變時,執行fn 
gulp.src(glob):置需要處理的檔案的路徑,可以是多個檔案以陣列的形式,也可以是正則 
gulp.dest(path[, options]):設定生成檔案的路徑

glob:可以是一個直接的檔案路徑。他的含義是模式匹配。
gulp將要處理的檔案通過管道(pipe())API導向相關外掛。通過外掛執行檔案的處理任務。

2.3.1 src()

gulp的src方法用於產生資料流,它的引數表示想要處理的檔案,這些指定的檔案會轉換為資料流。引數的寫法一般有以下幾種形式。

  • js/app.js:指定確切的檔名。
  • js/*.js:某個目錄所有後綴名為js的檔案。
  • js/**/*.js:某個目錄及其所有子目錄中的所有後綴名為js的檔案。
  • !js/app.js:除了js/app.js以外的所有檔案。
  • *.+(js|css):匹配專案根目錄下,所有後綴名為js或css的檔案。

src方法的引數還可以是一個數組,用來指定多個成員

gulp.src(['js/**/*.js', '!js/**/*.min.js'])
2.3.2 dest()

dest方法將管道的輸出寫入檔案,同時將這些輸出繼續輸出,所以可以依次呼叫多次dest方法,將輸出寫入多個目錄。如有目錄不存在,將會被新建

gulp.src('./client/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('./build/templates'))
.pipe(minify())
.pipe(gulp.dest('./build/minified_templates'));

dest方法還可以接受第二個引數,表示配置物件

gulp.dest('build', { cwd: './app', mode: '0644' })

配置物件有兩個欄位,cwd欄位指定寫入路徑的基準目錄,預設是當前目錄;mode欄位指定寫入目錄的許可權,預設是0777.

2.3.3 task()

task方法用於定義具體的任務。它的第一個引數是任務名,第二個引數是任務函式

gulp.task('greet', function () {
console.log('Hello world!');
});

task方法還可以按指定順序執行一組任務

gulp.task('build', ['css', 'js', 'imgs']);

上面程式碼先指定build任務,它由css、js、imgs三個任務所組成,task方法會併發執行這三個任務。注意,由於每個任務都是非同步呼叫,所以沒有辦法保證js任務的開始執行的時間,正是css任務執行結束。

如果希望各個任務嚴格按次序執行,可以把前一個任務寫成後一個任務的依賴模組。

gulp.task('css', ['greet'], function () {
// Deal with CSS here
});

上面程式碼表明,css任務依賴greet任務,所以css一定會在greet執行完成後再執行。

task方法的回撥函式,還可以接受一個函式作為引數,這對執行非同步任務非常有用。

// 執行shell命令
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
// build Jekyll
exec('jekyll build', function(err) {
if (err) return cb(err); // return error
cb(); // finished task
});
});

如果一個任務的名字是default,就表明它是預設任務,在命令列直接輸入gulp命令,就會執行該任務

gulp.task('default', ['styles', 'jshint', 'watch']);

直接使用gulp,就會執行styles,jshint,watch三個任務

2.3.4 watch()

watch方法用於指定需要監控的檔案,一旦這些檔案傳送變動,就執行指定任務

當然也可以用回撥函式代替指定任務

gulp.task('watch', function(){
gulp.watch('src/**/*',['default']);
})
//或者
gulp.task('watch', function(){
gulp.watch('src/**/*',function(){
//do something
});
})

另一種寫法是watch方法所監控的檔案傳送變動時,可能會觸發一些事件,如:

change:檔案傳送變動時觸發

end:回撥函式執行完畢時觸發

error:發生錯誤時觸發

ready:當開始監聽檔案時觸發

nomatch:沒有匹配的監聽檔案時觸發

2.4 gulp plugins

常用外掛

sass的編譯

自動新增css字首

壓縮css

js程式碼校驗

合併js程式碼

壓縮js程式碼

壓縮圖片

自動重新整理頁面

圖片快取(只有圖片替換了才壓縮)

更改提醒

清除檔案

(gulp-ruby-sass)

(gulp-autofixer)

(gulp-minify-css)

(gulp-jshint)

(gulp-concat)

(gulp-uglify)

(gulp-imagemin)

(gulp-livereload)

(gulp-cache)

(gulp-notify)

(gulp-clean)

http://gulpjs.com/plugins/    在gulp官網還有很多可選擇的外掛,大約600多個,這些外掛的核心是,一個外掛只做一件事!

3、gulp and grunt

3.1 工作流程

grunt的工作流程:讀檔案、修改檔案、寫檔案、讀檔案、修改檔案、寫檔案.....

gulp的工作流程:檔案流--檔案流--檔案流......因為grunt操作會建立臨時檔案,會有頻繁的IO操作,而gulp使用的是流操作,一直是在記憶體中處理,直到輸出結果, 因此gulp在效率上確實遠勝grunt。

3.2 差異和不同

  • 流:Gulp是一個基於流的構建系統,使用程式碼優於配置的策略。
  • 外掛:Gulp的外掛更純粹,單一的功能,並堅持一個外掛只做一件事。
  • 程式碼優於配置:維護Gulp更像是寫程式碼,而且Gulp遵循CommonJS規範,因此跟寫Node程式沒有差別。
  • 沒有產生中間檔案

3.3 I/O流程的不同

  • 使用grunt的I/O過程中會產生一些中間態的臨時檔案,一些任務生成臨時檔案,其他任務可能會基於臨時檔案再做處理並生成最終構建後的檔案
  • 使用gulp的優勢就是利用流的方式進行檔案的處理,通過管道將多個任務和操作連線起來,因此只有一次I/O的過程,流程更清晰,更純粹

4、 參考資料