P1 簡介
gulp是基于Nodejs的自動任務運行器, 它能自動化地完成 javascript/coffee/sass/less/html/image/css 等文件的的測試、檢查、合并、壓縮、格式化、瀏覽器自動刷新、部署文件生成,并監聽文件在改動后重復指定的這些步驟。在實現上,她借鑒了Unix操作系統的管道(pipe)思想,前一級的輸出,直接變成后一級的輸入,使得在操作上非常簡單。通過本文,我們將學習如何使用Gulp來改變開發流程,從而使開發更加快速高效。
gulp 和 grunt 非常類似,但相比于 grunt 的頻繁 IO 操作,gulp 的流操作,能更快地更便捷地完成構建工作。
P2 安裝
可替換淘寶鏡像:
npm install cnpm -g --registry=https://registry.npm.taobao.org
2.1 全局安裝 gulp:
$ npm install -g gulp
查看是否正確安裝:命令提示符執行gulp -v
,出現版本號version 3.9.1
即為正確安裝。
如果顯示'glup' 不是內部或外部命令,也不是可運行的程序或批處理文件。
,請確定你是否打對字,是gulp
,而不是glup
!!!這里我故意打錯字你也發現不了。
2.2 作為項目的開發依賴(devDependencies)安裝:
$ npm install --save-dev gulp
P3 Gulp API整理
gulp只有四個API:
task
,watch
,src
,和dest
3.1 gulp.task(name[, deps], fn)
name:任務名;
deps:StringArray
(可選),一個包含任務列表的數組,這些任務會在你當前任務運行之前完成;
fn:任務操作函數function() {}
.
//執行完one, two, three任務后再執行four
gulp.task('four', ['one', 'two', 'three'], function() {
return gulp.src(path)
.pipe(someplugin());
//或其他事
});
3.2 gulp.src(globs[, options])
src方法是指定需要處理的源文件的路徑,gulp借鑒了Unix操作系統的管道(pipe)思想,前一級的輸出,直接變成后一級的輸入,gulp.src返回當前文件流至可用插件;
globs:String 或 Array
,需要處理的源文件匹配符路徑
**通配符路徑匹配: **
-
src/a.js
:指定具體文件 -
*
:匹配所有文件src/*.js
(包含src下的所有js文件) -
**
:匹配0個或多個子文件夾src/**/*.js
(包含src的0個或多個子文件夾下的js文件); -
{}
:匹配多個屬性src/{a,b}.js
(包含a.js和b.js文件)src/*.{jpg,png,gif}
(src下的所有jpg/png/gif文件); -
!
:排除文件!src/a.js
(不包含src下的a.js文件);
var gulp = require('gulp'),
less = require('gulp-less');
gulp.task('testLess', function () {
//gulp.src('less/test/style.less')
gulp.src(['less/**/*.less','!less/{extend,page}/*.less'])
.pipe(less())
.pipe(gulp.dest('./css'));
});
options: (可選) Object,有3個屬性buffer、read、base
-
options.buffer
:Boolean
默認:true 設置為false,將返回file.content的流并且不緩沖文件,處理大文件時非常有用; -
options.read
:Boolean
默認:true 設置false,將不執行讀取文件操作,返回null; -
options.base
:String
設置輸出路徑以某個路徑的某個組成部分為基礎向后拼接,具體看下面示例:
gulp.src('client/js/**/*.js')
.pipe(minify())
.pipe(gulp.dest('build')); // Writes 'build/somedir/somefile.js'
gulp.src('client/js/**/*.js', { base: 'client' })
.pipe(minify())
.pipe(gulp.dest('build')); // Writes 'build/js/somedir/somefile.js'
異步任務支持
只有當fn
接受一個 callback,或者返回一個 promise 或 stream任務 才可以異步執行,且task默認以最大的并發數執行,即gulp 會一次性運行所有的 task 并且不做任何等待。
//接受一個 callback
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
// 編譯 Jekyll
exec('jekyll build', function(err) {
if (err) return cb(err); // 返回 error
cb(); // 完成 task
});
});
//返回一個 stream
gulp.task('somename', function() {
var stream = gulp.src('client/**/*.js')
.pipe(minify())
.pipe(gulp.dest('build'));
return stream;
});
//返回一個 promise
var Q = require('q');
gulp.task('somename', function() {
var deferred = Q.defer();
// 執行異步的操作
setTimeout(function() {
deferred.resolve();
}, 1);
return deferred.promise;
});
當然,如果你想要任務按照一定的順序執行。例如有兩個task,"one" 和 "two",在 "one" 中返回一個cb,或stream,promise,讓系統知道什么時候它會執行完畢; 在 "two" 中添加提示告訴系統 "two" 需要依賴 "one" 完成,即下面給出的栗子:
var gulp = require('gulp');
// 返回一個 callback,因此系統可以知道它什么時候完成
gulp.task('one', function(cb) {
// 做一些事 -- 異步的或者其他的
cb(err); // 如果 err 不是 null 或 undefined,則會停止執行,且注意,這樣代表執行失敗了
});
// 定義一個所依賴的 task 必須在這個 task 執行之前完成
gulp.task('two', ['one'], function() {
// 'one' 完成后
});
gulp.task('default', ['one', 'two']);
3.3 gulp.dest(path[, options])
dest方法是指定處理完后文件輸出的路徑
path:String or Function
指定文件輸出路徑,或者定義函數返回文件輸出路徑亦可
options:Object
,有2個屬性cwd、mode
-
options.cwd
:String
默認:process.cwd()
:當前腳本的工作目錄的路徑 當文件輸出路徑為相對路徑將會用到 -
options.mode
:String
默認:0777
指定被創建文件夾的權限
3.4 gulp.watch(glob [, opts], tasks)or
gulp.watch(glob [, opts, cb])
watch方法是用于監聽文件變化,文件一修改就會執行指定的任務
glob: String or StringArray
需要處理的源文件匹配符路徑。
opts: Object
(可選) 具體參看 gaze;
tasks: StringArray
需要執行的任務的名稱數組;
cb(event): Function()
每次文件變化執行的回調函數;
-
event.type
:String
發生的變動的類型:added
,changed
或者deleted
-
event.path
:String
觸發了該事件的文件的路徑。
P4 新建gulpfile.js文件
說明:gulpfile.js是gulp項目的配置文件,是位于項目根目錄的普通js文件(其實將gulpfile.js放入其他文件夾下亦可)
我們將要使用Gulp插件來完成我們以下任務:
- sass的編譯(gulp-sass)
- 自動添加css前綴(gulp-autoprefixer)
- 壓縮css(gulp-minify-css)
- js代碼校驗(gulp-jshint)
- 合并js文件(gulp-concat)
- 壓縮js代碼(gulp-uglify)
- 壓縮圖片(gulp-imagemin)
- 自動刷新頁面(gulp-livereload)
- 圖片緩存,只有圖片替換了才壓縮(gulp-cache)
- 更改提醒(gulp-notify)
- 修改文件名(gulp-rename)
安裝這些插件需要運行如下命令:
npm install gulp-sass gulp-autoprefixer gulp-minify-css gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache --save-dev
//成功安裝后在package.json中出現版本信息
{
"devDependencies": {
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.1",
"gulp-cache": "^0.4.6",
"gulp-concat": "^2.6.1",
"gulp-imagemin": "^3.2.0",
"gulp-jshint": "^2.0.4",
"gulp-livereload": "^3.8.1",
"gulp-minify-css": "^1.2.4",
"gulp-notify": "^3.0.0",
"gulp-rename": "^1.2.2",
"gulp-sass": "^3.1.0",
"gulp-uglify": "^2.1.2"
}
}
更多插件請點這里 gulp.js插件
4.1 加載插件:
// Load plugins
var gulp = require('gulp'),
sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
cache = require('gulp-cache'),
livereload = require('gulp-livereload');
4.2 建立任務:
4.2.1 編譯sass、自動添加css前綴和壓縮
首先我們編譯sass,添加前綴,保存到我們指定的目錄下面,還沒結束,我們還要壓縮,給文件添加 .min 后綴再輸出壓縮文件到指定目錄,最后提醒任務完成了:
// Styles任務
gulp.task('styles', function() {
//編譯sass
return gulp.src('stylesheets/main.scss')
.pipe(sass())
//添加前綴
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
//保存未壓縮文件到我們指定的目錄下面
.pipe(gulp.dest('stylesheets'))
//給文件添加.min后綴
.pipe(rename({ suffix: '.min' }))
//壓縮樣式文件
.pipe(minifycss())
//輸出壓縮文件到指定目錄
.pipe(gulp.dest('assets'))
//提醒任務完成
.pipe(notify({ message: 'Styles task complete' }));
});
4.2.2 js代碼校驗、合并和壓縮
// Scripts任務
gulp.task('scripts', function() {
//js代碼校驗
return gulp.src('javascripts/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
//js代碼合并
.pipe(concat('all.js'))
//給文件添加.min后綴
.pipe(rename({ suffix: '.min' }))
//壓縮腳本文件
.pipe(uglify())
//輸出壓縮文件到指定目錄
.pipe(gulp.dest('assets'))
//提醒任務完成
.pipe(notify({ message: 'Scripts task complete' }));
});
4.2.3 圖片壓縮
// Images
gulp.task('images', function() {
return gulp.src('images/*')
.pipe(cache(imagemin({
optimizationLevel: 3, //類型:Number默認:3取值范圍:0-7(優化等級)
progressive: true, //類型:Boolean 默認:false 無損壓縮jpg圖片
interlaced: true, //類型:Boolean 默認:false 隔行掃描gif進行渲染
multipass: true //類型:Boolean 默認:false 多次優化svg直到完全優化
})))
.pipe(gulp.dest('images'))
.pipe(notify({ message: 'Images task complete' }));
});
4.2.4 事件監聽
// Watch
gulp.task('watch', function() {
// Watch .scss files
gulp.watch('stylesheets/*.scss', ['styles']);
// Watch .js files
gulp.watch('javascripts/*.js', ['scripts']);
// Watch image files
gulp.watch('images/*', ['images']);
// Create LiveReload server
livereload.listen();
// Watch any files in assets/, reload on change
gulp.watch(['assets/*']).on('change', livereload.changed);
});
4.2.5 定義默認任務
栗子里的第二個參數是一個包含任務列表的數組,這些任務會在你當前任務運行之前完成。
gulp.task('default', ['styles', 'scripts', 'images', 'watch'], function() {
console.log('Everthing is done!');
});
P5 運行gulp
5.1 命令提示符執行
- 命令提示符執行
gulp 任務名稱
, 如gulp styles
- 當執行
gulp default
或gulp
將會調用default任務里的所有任務
5.2 使用WebStorm運行gulp任務
將項目導入WebStorm,右鍵gulpfile.js 選擇“Show Gulp Tasks”打開Gulp窗口,若出現“No task found”,選擇右鍵”Reload tasks”,雙擊運行即可。