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”,双击运行即可。