>npm install -g gulp #全局安装
>npm install gulp (--save-dev) #每个项目中也要单独安装一次,且添加到package.json中
#####1. 核心API
gulp.task(name[, deps], fn)
gulp.src(globs[, options]) 可以没有返回,[node-glob语法](https://github.com/isaacs/node-glob)
gulp.dest(path[, options]) 可pipe到多个文件夹,不存在自动创建
gulp.watch(glob[, opts], tasks) 可返回watcher对象,另行添加事件
gulp.watch(glob[, opts], cb)
```
//gulp.watch(glob[, opts], tasks)
gulp.watch('pattern',['taskname'])
watcher.on('change|end|error|ready|nomatch', function(event){
//event.type 变动类型added、changed、deleted
//event.path 文件路径
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
//gulp.watch(glob[, opts], cb)
gulp.watch('js/**/*.js', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
watcher.files()监听的文件列表,
watcher.end(),
watcher.add(glob),
watcher.remove(filepath)
```
#####2. 命令行
`gulp`
`gulp taskname`
#####3. 常用插件:
- gulp-load-plugins 自动从package.json中加载gulp-\*或gulp.*插件并以驼峰形式命名,`$ = require('gulp-load-plugins')();`
######3.1 JS相关
- gulp-uglify 压缩js
- gulp-jshint JS语法检查
- gulp-sourcemaps 帮助调试压缩后的代码
- gulp-mocha 测试node.js程序
- [gulp-jasmine](https://www.npmjs.com/package/gulp-jasmine) 写单元测试
- [browserify](http://npm.taobao.org/package/browserify) 转换模块化写法被浏览器识别,**gulp-browserify插件已不再维护**
- gulp-react 转换jsx代码
- gulp-babel 转换es6代码
- gulp-angular-teamplatecache
- gulp-ng-annotate
######3.2 CSS相关
- gulp-minify-css 压缩css
- [gulp-uncss](https://www.npmjs.com/package/gulp-uncss) 去除多余CSS
- [gulp-csso](https://www.npmjs.com/package/gulp-csso) 更深入地优化CSS
- gulp-less 编译less
- gulp-sass 编译sass
- gulp-stylus
- gulp-autoprefixer 自动补全css前缀
- [Critical](https://www.npmjs.com/package/critical) 生成行内CSS
######3.3 图片相关
- gulp-imagemin 压缩图片
- [gulp-cache](https://www.npmjs.com/package/gulp-cache) 图片快取,只有更改过的图片会进行压缩
- [gulp-spritesmith](https://github.com/twolfson/gulp.spritesmith)
######3.4 文件
- gulp-if
- gulp-filter 把stream里的文件根据一定的规则进行筛选过滤
- gulp-flatten 过滤掉路径,提取出文件
- vinyl-paths 简单获取stream中每个文件的路径
- [gulp-watch-path](https://github.com/nimojs/gulp-watch-path) 监听改变文件的路径 watchPath(event, search, replace, distExt),event是gulp.watch回调函数的event,search是需要被替换的起始字符串,replace是新的字符串,distExt扩展名(非必填)
- gulp-useref 根据注释将HTML中需要合并压缩的区块找出来,对区块内的所有文件进行合并
- gulp-rev 负责在文件名后追加hash
- gulp-rev-replace 负责把最终的文件名替换回HTML中去
- gulp-concat 拼接
- gulp-clean
- gulp-rename 重命名
- gulp-header 在压缩后的js、css文件中添加头部注释`.pipe(getHeader())`
- merge-stream 将多个steam合成一个返回
- [del](https://www.npmjs.com/package/del) 处理支持glob匹配的删除,del([glob], callback)
- gulp-rimraf 删除文件夹
######3.5 gulp执行
- [run-sequence](https://www.npmjs.com/package/run-sequence) 指定任务顺序,要求task返回一个stream或者回调式调用
- [gulp-util](http://npm.taobao.org/package/gulp-util)
- stream-combiner2 捕获错误信息
- gulp-plumber 一旦pipe中的某一steam报错,保证下面的steam还继续执行
- yargs 处理命令行参数
- gulp-bytediff 统计文件大小变化的工具
- gulp-print 打印出stream里面的所有文件名
- vinyl-buffer 将vinyl对象内容中的Stream转换为Buffer,**因为常规流和vinyl文件对象有差异**
- vinyl-source-stream 将常规流转换为包含Stream的vinyl对象
- gulp-task-listing 打印出gulpfile.js中定义的所有task `gulp.task('help', $.taskListing)`
######3.6 其它
- gulp-minify-html 压缩HTML
- gulp-jade 编译jade模板
- gulp-jscs
- gulp-cheerio
- gulp-notify
- gulp-replace
- [open](http://npm.taobao.org/package/open) Open a file or url in the user's preferred application.
- [browser-sync]() 实时刷新浏览器和其它设备
- gulp-livereload 自动刷新浏览器.pipe(gulp.dest('css')).pipe(livereload())
- connect-ssi
- [gulp-rsync](https://www.npmjs.com/package/gulp-rsync) 直接部署dist文件到生产环境
- gulp-bump 升级版本
- wiredep 将bower.json中声明的dependence自动的包含到html中
- gulp-inject
- connect-history-api-fallback
- proxy-middleware
- gulp-protractor
- gulp-order
- connect-ssi
#####4. 实例
```
//初始化加载gulp
var gulp = require('gulp');
gulp.task('default',function(){
console.log('hello world'); //任务就是打印hello world
});
//压缩js
var uglify = require('gulp-uglify');
gulp.task('uglify script', function() {
gulp.src('js/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
//压缩CSS
var minifyCSS = require('gulp-minify-css')
var autoprefixer = require('gulp-autoprefixer')
gulp.task('minify css', function () {
gulp.src('css/*.css')
.pipe(sourcemaps.init())
.pipe(autoprefixer({
browsers: 'last 2 versions'
}))
.pipe(minifyCSS())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist/css'))
});
//压缩图片
var imagemin = require('gulp-imagemin');
var cache = require('gulp-cache');
gulp.task('imagesmin', function () {
//gulp.src('images/*.*')
gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
//.pipe(imagemin({ progressive: true }))
.pipe(cache(imagemin({
interlaced: true
})))
.pipe(gulp.dest('dist/images'))
});
// 在命令行使用 gulp auto 启动此任务
var gutil = require('gulp-util');
var watchPath = require('gulp-watch-path'); // 默认重新编译指定目录下的所有文件,需要与event配合
var combiner = require('stream-combiner2');
var sourcemaps = require('gulp-sourcemaps');
var handleError = function (err) {
var colors = gutil.colors;
console.log('\n')
gutil.log(colors.red('Error!'))
gutil.log('fileName: ' + colors.red(err.fileName))
gutil.log('lineNumber: ' + colors.red(err.lineNumber))
gutil.log('message: ' + err.message)
gutil.log('plugin: ' + colors.yellow(err.plugin))
};
gulp.task('watch', function () {
gulp.watch('css/*.css', ['minify css'])
//gulp.watch('js/*.js', ['uglify script']) // 1.指定任务
gulp.watch('src/js/**/*.js', function (event) { // 2.在回调中直接处理
console.log(event);
var paths = watchPath(event, 'src/', 'dist/');
/*
paths
{ srcPath: 'src/js/log.js',
srcDir: 'src/js/',
distPath: 'dist/js/log.js',
distDir: 'dist/js/',
srcFilename: 'log.js',
distFilename: 'log.js' }
*/
gutil.log(gutil.colors.green(event.type) + ' ' + paths.srcPath);
gutil.log('Dist ' + paths.distPath);
/*
//正确写法,无错误处理
gulp.src(paths.srcPath)
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(paths.distDir));
*/
//捕获错误
var combined = combiner.obj([
gulp.src(paths.srcPath),
sourcemaps.init(),
autoprefixer({
browsers: 'last 2 versions'
}),
uglify(),
sourcemaps.write('./'),
gulp.dest(paths.distDir)
]);
// 任何在上面的 stream 中发生的错误,都不会抛出,而是会被监听器捕获
//combined.on('error', console.error.bind(console));
combined.on('error', handleError);
console.log('\n')
console.log(event.type + ': ' + paths.srcPath)
console.log('dist: ' + paths.distPath)
return combined;
})
gulp.watch('images/*.*)', ['images'])
});
//less转css
var less = require('gulp-less');
gulp.task('less', function () {
return gulp.src('./src/less/*.less')
.pipe(less())
.pipe(gulp.dest('./dest'));
});
//sass转css
var sass = require('gulp-sass');
gulp.task('sass',function(){
/*
return gulp.src('./src/scss/*.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
.pipe(browserSync.reload({ //自动刷新浏览器
stream: true
}));
*/
return sass('src/sass/')
.on('error', function (err) {
console.error('Error!', err.message);
})
.pipe(sourcemaps.init())
.pipe(minifycss())
.pipe(autoprefixer({
browsers: 'last 2 versions'
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist/css'))
});
//JSX转JS、ES6转换
var react = require('gulp-react');
var babel = require('gulp-babel');
gulp.task('react',['less','sass'], function () {
return gulp.src('./src/myui.js')
.pipe(react())
.pipe(babel({
presets: ['babel-preset-es2015'] //需要安装babel-present-es2015
}))
.pipe(gulp.dest('./dest'));
});
//mocha测试
var mocha = require('gulp-mocha');
gulp.task('mocha test', function () {
return gulp.src('./src/test2.js')
.pipe(mocha());
});
//jasmine测试
var jasmine = require('gulp-jasmine');
gulp.task('jasmine test', ['mocha test'], function () {
return gulp.src('./src/test1.js')
.pipe(jasmine());
});
//模块化转换
var browserify = require('gulp-browserify');
gulp.task('browserify', function () {
return gulp.src('./src/main.js')
.pipe(browserify())
.pipe(uglify())
.pipe(gulp.dest('./build'));
});
//文件复制
gulp.task('copy file', function () {
gulp.src('src/fonts/**/*')
.pipe(gulp.dest('dist/fonts/'))
});
gulp.task('default', ['browserify', 'uglify script', 'less', 'sass', 'minify css', 'imagesmin', 'mocha test', 'jasmine test', 'react', 'copy file', 'watch']);
//格式化输出信息
gulp.task('default', function () {
gutil.log('message')
gutil.log(gutil.colors.red('error'))
gutil.log(gutil.colors.green('message:') + "some")
});
//实时刷新浏览器
var browserSync = require('browser-sync');
gulp.task('browserSync', function() {
browserSync({
server: {
baseDir: 'app'
},
})
});
//判断文件类型选择压缩方式
var gulpIf = require('gulp-if');
gulp.task('useref', function(){
return gulp.src('app/*.html')
//.pipe(uglify())
.pipe(gulpIf('*.css', minifyCSS()))
.pipe(gulpIf('*.js', uglify()))
//.pipe(flag ? uglify() : $.util.noop()) $.util.noop()返回一个空
.pipe(useref())
.pipe(gulp.dest('dist'))
});
//清理文件
var del = require('del');
gulp.task('clean:dist', function(callback){
del(['dist/**/*', '!dist/images', '!dist/images/**/*'], callback)
});
gulp.task('clean', function(callback) {
del('dist');
return cache.clearAll(callback);
});
//指定执行顺序
var runSequence = require('run-sequence');
gulp.task('build', function (callback) {
runSequence('clean:dist', //第一个执行
['sass', 'useref', 'images', 'fonts'], //同时执行
callback
)
});
//生成雪碧图和css文件
var spritesmith = require('gulp.spritesmith');
gulp.task('sprite', function () {
var spriteData = gulp.src('images/*.png').pipe(spritesmith({
imgName: 'sprite.png',
cssName: 'sprite.css',
cssFormat: 'scss',
cssTemplate: 'scss.template.mustache',
cssOpts: 'spriteSrc'
}));
return spriteData.pipe(gulp.dest('path/to/output/'));
});
//vinyl-paths
var stripDebug = require('gulp-strip-debug'); // 仅用于本例做演示
var vinylPaths = require('vinyl-paths');
gulp.task('clean:tmp', function () {
return gulp.src('tmp/*')
.pipe(stripDebug())
.pipe(gulp.dest('dist'))
.pipe(vinylPaths(del));
});
//统计文件大小变化
gulp.src('**/*.html')
.pipe($.bytediff.start())
.pipe($.minifyHtml({empty: true}))
.pipe($.bytediff.stop(bytediffFormatter))
.pipe(gulp.dest('dist'));
function bytediffFormatter (data) {
var difference = (data.savings > 0) ? ' smaller.' : ' larger.';
return data.fileName + ' went from ' +
(data.startSize / 1000).toFixed(2) + ' kB to ' +
(data.endSize / 1000).toFixed(2) + ' kB and is ' +
formatPercent(1 - data.percent, 2) + '%' + difference;
}
//添加注释 gulp-header
function getHeader () {
var pkg = require('package.json');
var template = ['/**',
' * <%= pkg.name %> - <%= pkg.description %>',
' * @authors <%= pkg.authors %>',
' * @version v<%= pkg.version %>',
' * @link <%= pkg.homepage %>',
' * @license <%= pkg.license %>',
' */',
''
].join('\n');
return $.header(template, {
pkg: pkg
});
}
// 过滤 gulp-filter
$.filter('**/a/*.js');
gulp.src('**/*.js')
.pipe(action1())
.pipe(filter)
.pipe(action2())
.pipe(filter.restore())
.pipe(gulp.dest('dist'))
//gulp-plumber
gulp.task('build', ['jslint', 'xxxx']);
gulp.task('jslint', function () {
return gulp
.src(config.js.all)
.pipe($.plumber())
.pipe($.jshint())
.pipe($.jscs());
});
//merge-stream
var merge = require('merge-stream');
gulp.task('jade', function () {
var stream1 = jade(src1, dest1);
var stream2 = jade(src2, dest2);
return merge(stream1, stream2);
});
function jade (src, dest) {
return gulp
.src(src)
.pipe($.jade())
.pipe(gulp.dest(dest));
}
```
#####5. 注意事项
gulp.src()函数用字符串匹配一个文件或文件的编号(glob),然后创建一个对象流来代表这些文件。
gulp内部使用node-glob来从指定的glob中获取文件。
`js/app.js` 精确匹配
`js/*.js` 匹配js目录下所有js文件
`**/*.js` 匹配当前目录及其子目录下的所有scss文件
`js/*/.js` 匹配js目录及其子目录下所有js文件
`!js/app.js` 排除js/app.js
`*.+(js|css)` 匹配根目录下所有后缀为.js或.css的文件
`gulp.src(['js/**/*.js', '!js/**/*.min.js'])` 匹配未压缩的
`*`匹配文件路径中的0个或多个字符,但不会匹配路径分隔符,除非路径分隔符出现在末尾
`\**`匹配路径中的0个或多个目录及其子目录,需要单独出现,即它左右不能有其他东西了。如果出现在末尾,也能匹配文件。
`?`匹配文件路径中的一个字符(不会匹配路径分隔符)
`[...]`匹配方括号中出现的字符中的任意一个,当方括号中第一个字符 为^或!时,则表示不匹配方括号中出现的其他字符中的任意一个,类似js正则表达式中的用法
`!(pattern|pattern|pattern)`匹配任何与括号中给定的任一模式都不匹配的
`?(pattern|pattern|pattern)`匹配括号中给定的任一模式0次或1次,类似于js正则中的(pattern|pattern|pattern)?
`+(pattern|pattern|pattern)`匹配括号中给定的任一模式至少1次,类似于js正则中的(pattern|pattern|pattern)+
`_(pattern|pattern|pattern)`匹配括号中给定的任一模式0次或多次,类似于js正则中的(pattern|pattern|pattern)_
`@(pattern|pattern|pattern)`匹配括号中给定的任一模式1次,类似于js正则中的(pattern|pattern|pattern)
#####6. 技巧
整合streams来处理错误
删除文件和文件夹
使用watchify加速browserify编译
增量编译打包,包括处理整所涉及的所有文件
将buffer变为stream(内存中的内容)
在gulp中运行Mocha测试
仅仅传递更改过的文件
从命令行传递参数
只编译被更改过的文件
每个文件夹生成单独一个文件
串行方式运行任务
拥有实时重载(live-reloading)和CSS注入的服务器
通过stream工厂来共享stream
指定一个新的CWD(当前工作目录)
分离任务到多个文件中
使用外部配置文件
在一个任务重使用多个文件来源
Browserify+Uglify2和sourcemaps
Browserify+Globs
同时输出一个压缩过的和未压缩版本的文件
改变版本号以及创建一个git tag
SWig以及YAML front-matter模板
#####7. 参考文章
[Gulp开发教程(翻译)](http://www.w3ctech.com/topic/134)
[gulp入门指南](http://wiki.jikexueyuan.com/project/gulp-book/chapter7.html)
[Gulp新手入门教程](http://www.tuicool.com/articles/QzaqAbF)
[Gulp使用指南](http://www.techug.com/gulp)
[spritemith](http://www.w3ctrain.com/2015/12/09/generating-sprites-with-gulp/)
[gulp API文档](http://www.gulpjs.com.cn/docs/api/)
[常用gulp插件介绍(一)](http://pinkyjie.com/2015/08/02/commonly-used-gulp-plugins-part-1/)
[常用gulp插件介绍(二)](http://pinkyjie.com/2015/08/12/commonly-used-gulp-plugins-part-2/)
[在Gulp 中使用 Browserify](http://www.tuicool.com/articles/MFjAZn6)
[Gulp--项目的愿景、过去和将来](http://sentsin.com/web/204.html)
[Gulp思维——Gulp高级技巧](http://segmentfault.com/a/1190000000711469)
[Gulp错误管理](http://csspod.com/error-management-in-gulp/?utm_source=tuicool&utm_medium=referral)
[chalk处理命令行打印着色](https://github.com/chalk/chalk)