内容基本整理于gulp-book chapter7,我有一点增改。
1. 初始安装
npm init
创建package.json
保存所有npm install --save-dev gulp-xxx
模块依赖和模块版本。
npm install gulp --save-dev
安装gulp到项目package.json
中增加下列代码,声明此项目的开发依赖 gulp。
"devDependencies": {
"gulp": "^3.9.1"
}
安装项目中用到的其他模块
例如
npm install gulp-uglify --save-dev
package.json
的”devDependencies”中继续增加依赖声明。
在gulpfile.js
已配置情况下直接输入npm install
命令即可检测package.json
中的 “devDependencies”并安装所有依赖。
2. 设计目录结构
src
源码存放目录dist
编译压缩后的文件存放目录
dist
和dest
区别^foot:
dist是指distribution——分配,分发——发布完成的文件夹一般命名dist
dest则是destination——目的地,终点——用于grunt文件路径相关的配置项,一般会和src配对出现。比如文件压缩插件:压缩源(src)文件,生成压缩包到(dest)。
3. 用gulp-util设置 CLI 输出文字的颜色
1 | // 获取 gulp 和 gulp-util 模块 |
经过测试rgb颜色不支持。
4. 配置 JS 任务
glob
glob模式是指 shell 所使用的简化了的正则表达式。nodejs的glob模块是glob模式的javascript实现版本。
匹配规则 ^foot2
*
匹配任意 0 或多个任意字符?
匹配任意一个字符[...]
若字符在中括号中,则匹配。若以!
或^
开头,若字符不在中括号中,则匹配!(pattern|pattern|pattern)
不满足括号中的所有模式则匹配?(pattern|pattern|pattern)
满足 0 或 1 括号中的模式则匹配+(pattern|pattern|pattern)
满足 1 或 更多括号中的模式则匹配*(a|b|c)
满足 0 或 更多括号中的模式则匹配@(pattern|pat*|pat?erN)
满足 1 个括号中的模式则匹配**
跨路径匹配任意字符gulp-uglify 压缩js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var gulp = require('gulp')
var uglify = require('gulp-uglify')
gulp.task('uglifyjs', function () {
//选则 src/js 目录下的所有 js 文件
gulp.src('src/js/**/*.js')
//压缩
.pipe(uglify())
//将压缩后的文件输出到 dist/js 目录下
.pipe(gulp.dest('dist/js'))
})
gulp.task('default', function () {
//当 gulp.watch 检测到 src/js/ 目录下的js文件有修改时会将所有文件全部编译。
gulp.watch('src/js/**/*.js', ['uglifyjs'])
})
编辑 `src/js/log.js` 文件并保存,命令行更新,表示检测到 `src/js/**/*.js` 文件修改后重新编译所有 js。
![gulp-uglifyjs][4]
gulp-watch-path
gulp.watch(glob[, opts], tasks) gulp.watch(glob[, opts, cb])
监视文件,并且可以在文件发生改动时候做一些事情。它总会返回一个 EventEmitter 来发射(emit) change 事件。详见API。
gulp.watch
第二个参数为function
时的用法:1
2
3
4
5
6
7
8
9
10
11
12gulp.watch('src/js/**/*.js', function (event) {
console.log(event);
/*
当修改 src/js/log.js 文件时
event {
// 发生改变的类型,不管是添加,改变或是删除
type: 'changed',
// 触发事件的文件路径
path: '/Users/nimojs/Documents/code/gulp-book/demo/chapter7/src/js/log.js'
}
*/
})1
2
3gulp.watch('js/**/*.js', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});
[gulp-watch-path][6]
This is for the expansion of the gulp.watch(event)
利用 `gulp-watch-path` 配合 `event`(检测当前修改的js文件) 获取编译路径和输出路径:
**`watchPath(event, search, replace, distExt)`**
| 参数 | 说明 |
|--------|--------|
| event |`gulp.watch` 回调函数的 `event`|
| search |需要被替换的起始字符串|
| replace |第三个参数是新的的字符串|
| distExt |扩展名(非必填)|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var gulp = require('gulp')
var gutil = require('gulp-util')
var uglify = require('gulp-uglify')
var watchPath = require('gulp-watch-path')
gulp.task('watchjs', function () {
gulp.watch('src/js/**/*.js', function (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(uglify())
.pipe(gulp.dest(paths.distDir))
})
})
gulp.task('default', ['watchjs'])
![gulp watchjs][7]
stream-combiner2 捕获错误信息
Combining streams to handle errors
By using stream-combiner2 you can turn a series of streams into a single stream, meaning you only need to listen to the error event in one place in your code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var combiner = require('stream-combiner2');
var uglify = require('gulp-uglify');
var gulp = require('gulp');
gulp.task('test', function() {
var combined = combiner.obj([
gulp.src('bootstrap/js/*.js'),
uglify(),
gulp.dest('public/bootstrap')
]);
// any errors in the above streams will get caught
// by this listener, instead of being thrown:
combined.on('error', console.error.bind(console));
return combined;
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var gulp = require('gulp')
var gutil = require('gulp-util')
var uglify = require('gulp-uglify')
var watchPath = require('gulp-watch-path')
var combiner = require('stream-combiner2')
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('watchjs', function () {
gulp.watch('src/js/**/*.js', function (event) {
var paths = watchPath(event, 'src/', 'dist/')
gutil.log(gutil.colors.green(event.type) + ' ' + paths.srcPath)
gutil.log('Dist ' + paths.distPath)
var combined = combiner.obj([
gulp.src(paths.srcPath),
uglify(),
gulp.dest(paths.distDir)
])
combined.on('error', handleError)
})
})
gulp.task('default', ['watchjs'])
![捕获错误信息][10]
使用 SourceMap 进行压缩代码调试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37var gulp = require('gulp')
var gutil = require('gulp-util')
var uglify = require('gulp-uglify')
var watchPath = require('gulp-watch-path')
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('watchjs', function () {
gulp.watch('src/js/**/*.js', function (event) {
var paths = watchPath(event, 'src/', 'dist/')
gutil.log(gutil.colors.green(event.type) + ' ' + paths.srcPath)
gutil.log('Dist ' + paths.distPath)
var combined = combiner.obj([
gulp.src(paths.srcPath),
sourcemaps.init(),
uglify(),
sourcemaps.write('./'),
gulp.dest(paths.distDir)
])
combined.on('error', handleError)
})
})
gulp.task('default', ['watchjs'])生成对应的 .map 文件,可在浏览器中调试。
gulp-uglifyjs
压缩所有js文件。1
2
3
4
5
6
7
8
9
10gulp.task('uglifyjs', function () {
var combined = combiner.obj([
gulp.src('src/js/**/*.js'),
sourcemaps.init(),
uglify(),
sourcemaps.write('./'),
gulp.dest('dist/js/')
])
combined.on('error', handleError)
})
5. 配置 CSS 任务
gulp-clean-css
同js压缩。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18var cleancss = require('gulp-clean-css')
gulp.task('watchcss', function () {
gulp.watch('src/css/**/*.css', function (event) {
var paths = watchPath(event, 'src/', 'dist/')
gutil.log(gutil.colors.green(event.type) + ' ' + paths.srcPath)
gutil.log('Dist ' + paths.distPath)
gulp.src(paths.srcPath)
.pipe(sourcemaps.init())
.pipe(cleancss())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(paths.distDir))
})
})
gulp.task('default', ['watchjs','watchcss'])gulp-autoprefixer
autoprefixer 解析 CSS 文件并且添加浏览器前缀到CSS规则里。
gulp-autoprefixer1
2
3
4
5
6
7
8
9
10
11const gulp = require('gulp');
const autoprefixer = require('gulp-autoprefixer');
gulp.task('default', () =>
gulp.src('src/app.css')
.pipe(autoprefixer({
browsers: ['last 2 versions'],
cascade: false
}))
.pipe(gulp.dest('dist'))
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gulp.task('watchcss', function () {
gulp.watch('src/css/**/*.css', function (event) {
var paths = watchPath(event, 'src/', 'dist/')
gutil.log(gutil.colors.green(event.type) + ' ' + paths.srcPath)
gutil.log('Dist ' + paths.distPath)
gulp.src(paths.srcPath)
.pipe(sourcemaps.init())
.pipe(autoprefixer({
browsers: 'last 2 versions'
}))
.pipe(cleancss())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(paths.distDir))
})
})
![添加浏览器前缀][12]
gulp-clean-css
压缩所有css文件。1
2
3
4
5
6
7
8
9
10gulp.task('cleanCss', function () {
gulp.src('src/css/**/*.css')
.pipe(sourcemaps.init())
.pipe(autoprefixer({
browsers: 'last 2 versions'
}))
.pipe(cleancss())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist/css/'))
})
6. 配置 Less 任务
1 | var less = require('gulp-less') |
7. 配置 Sass 任务
1 | var sass = require('gulp-sass') |
8. 配置 image 任务
1 | var imagemin = require('gulp-imagemin') |
9. 配置文件复制任务
复制 src/fonts/
文件到 dist/
中
1 | gulp.task('watchcopy', function () { |
10. 总结
1 | var gulp = require('gulp') |
周末学习了gulp,最后把学习过的代码完整地打了一遍,调试了一会就全部编译成功了。也终于感觉到了gulp作为构建工具的方便快捷。楽しい!
今天再看看相关的扩展和别人的经验总结~