gulp.js – stream 驱动的自动构建工具
最近心情不太好,开始有点自暴自弃。所幸能够写点代码分分心……
开始接触一些前端的项目,就尝试着用一些看起来很 cool 的技术/工具。初步选定的工具包括 jade 、 stylus 和 coffee 。
可是做预编译实在是一个很麻烦的事情,直到我遇见了 gulp.js 。
gulp.js 是一个简洁明快的自动构建工具,官方文档也异常简洁清晰。主打“stream”式构建,配置文件写起来也是不太复杂。这里针对自己用到的一些插件做简单的介绍。
gulp-concat
是一个将多个文件合并到一起的插件。
gulp-clean
用来清理目标目录中的文件。
gulp-stylus
、gulp-coffee
和gulp-jade
用来预编译我的代码。
想要达到的效果是:
- 将一些静态文件复制到发布目录;
- 将框架的 css 与自己的 stylus 编译成的 css 合并;
- 将框架的 js 与自己的 coffee 合并;
- 将 jade 编译为 html 文件。
目录结构如下:
public/ 存放发布文件 src/ 存放源文件
实现思路:
清理发布目录
var clean = require('gulp-clean');
gulp.task('clean', function () {
return gulp.src('public').pipe(clean());
});
几乎是最简单的任务。将发布目录整个的删掉。
gulp.src
用于读取源文件,这里读取的是public
目录;然后将其 pipe 到 gulp-clean 插件,将其清理掉。
处理静态文件
gulp.task('static', function () {
gulp.src('src/img/**')
.pipe(gulp.dest('public/img/'));
gulp.src('src/fonts/**')
.pipe(gulp.dest('public/fonts/'));
});
和上面的范例类似,只不过用的是gulp.dest
,用于将 pipe 过来的文件发布到 public 目录。
注意这里的路径是 src/img/**
,表示对 img
目录下的文件进行递归处理。
构建 jade
var jade = require('gulp-jade');
gulp.task('html', function () {
return gulp.src(['src/jade/**/*.jade', '!src/jade/partial/**'])
.pipe(jade())
.pipe(gulp.dest('public/'));
});
这里只是换用了gulp-jade
插件而已。
需要注意的是,这次的路径传入进来的是个数组;数组会如同你想象的那样,将数组中的元素挨个匹配;!开头的表示去除src/jade/partial
目录下的所有 *.jade 文件;**/*.jade
则表示该目录下递归中所有的 jade 文件。
这里将 gulp 链 return 回去,是为了在处理依赖的时候,能够正确确定函数处理进度,以保证运行顺序。
合并 js 和 css
var concat = require('gulp-concat');
//合并 css
gulp.task('css', function () {
return gulp.src('src/css/*.css')
.pipe(concat('0.css'))
.pipe(gulp.dest('.tmp/css/'));
});
//处理 js
gulp.task('js', function () {
//加载jquery、modernizr、foundation、vue
return gulp.src([
'src/js/vendor/jquery.js',
'src/js/vendor/modernizr.js',
'src/js/foundation.min.js',
'src/js/vendor/vue.min.js'
])
.pipe(concat('0.js'))
.pipe(gulp.dest('.tmp/js/'));
});
这里用到的是gulp-concat
插件。它能把多个文件合并成为同一个。
这里将输出送到了 .tmp
目录下,是为了后续能够处理它。
编译 stylus 和 coffee
var stylus = require('gulp-stylus');
var coffee = require('gulp-coffee');
//stylus 编译
gulp.task('stylus', function () {
return gulp.src('src/styl/**/*.styl')
.pipe(stylus())
.pipe(concat('1.css'))
.pipe(gulp.dest('.tmp/css/'));
})
//处理 coffee
gulp.task('coffee', function () {
return gulp.src('src/coffee/**/*.coffee')
.pipe(coffee({
bare: true
}).on('error', gutil.log))
.pipe(concat('1.js'))
.pipe(gulp.dest('.tmp/js'));
});
这里依然将输出送到了 .tmp
下。接下来要将 .tmp
下的文件合并为真正能够使用的 css 和 js 文件。
合并临时 css 与 js 文件
gulp.task('concat-css', ['css', 'stylus'], function () {
return gulp.src('.tmp/css/*')
.pipe(concat('common.css'))
.pipe(gulp.dest('public/css'));
});
gulp.task('concat-js', ['js', 'coffee'], function () {
return gulp.src('.tmp/js/*')
.pipe(concat('common.js'))
.pipe(gulp.dest('public/js'));
});
这里用到的是 deps
也就是“依赖”语法。task 的第二个参数是一个数组。在执行这个任务时,会自动执行数组中的任务;并且,当且仅当数组中所有任务执行完毕后,才会执行后面的 function 中的任务。
这里的应用就是,在先合并好了框架的 css 和自己写的 stylus 编译完成之后,再将临时文件中的两组文件合并起来。
清理临时文件
gulp.task('concat-and-clean', ['concat-css', 'concat-js'], function () {
return gulp.src('.tmp').pipe(clean());
});
这里则是用到了刚刚提到的 gulp=clean
插件和 deps
语法。
默认动作
gulp.task('default', ['concat-and-clean', 'html', 'static']);
在命令行下,执行 gulp
时,则会自动执行 default
任务。这里定义的 default
任务没有事实上的动作;它只是同时执行上面所述的几个任务,然后自己退出。
监视改动
gulp.task('watch', ['default'], function () {
//js
gulp.watch('src/coffee/**', ['concat-js']);
//css
gulp.watch('src/styl/**', ['concat-css']);
//html
gulp.watch('src/jade/**', ['html']);
//静态
gulp.watch('src/img/**', ['static']);
})
gulp.watch
能够监视指定文件的改动,并启动任务;也就是说,当src/coffee/
中的文件改动时,gulp 会自动执行 concat-js
任务。
然后我们只需要在命令行中输入 gulp watch
,gulp 将会自动跑一轮 default
任务,然后监视我们的源文件;当发现文件变动时,将自动执行编译。
至此,我的 gulpfile.js
就编写完毕了。Enjoy it!