更简单的 JavaScript Task runner
在去年的时候,曾经写过一篇博客介绍Grunt: GruntJS初体验,以及当时使用的时候遇到的一些问题。
不过从那之后,就一直听说有一个更好用的Task runner – gulp。尽管现在才使用有点落伍了,但是还是想分享一下使用gulp轻松而愉快的经历。
gulp和Grunt一样都是通过项目根目录下的「配置文件」来进行「任务」的定义的。
配置文件
在我使用Grunt的经历看来,Grunt的配置文件比较固定:
相比而言,gulp的配置文件就像普通的Node文件一样:
var gulp = require('gulp');
gulp.task('default', function() {
// config task
});
从配置文件来看,gulp就要比Grunt简洁很多:任务的配置、注册、插件的load几乎在一个函数中完成。
流与插件
由于Grunt发展的时间较gulp而言要长的多,因此其社区也相对更为壮大,这导致的结果就是Grunt现有的插件共有3188个,而gulp只有745个(截至2014年7月27日)。
当然,插件的数量并不能说明一切。毕竟实际上对于项目而言并不需要依赖那么多的插件,就像NPM中有如此多的包而最常用的总是那么几个。相信对于gulp而言,插件的数量超越Grunt也可能只是时间问题。
这里就不赘述在Grunt中使用插件的方式了,如果没有使用过Grunt可以参考Grunt的官网中的示例。
需要提及的一点是,gulp自称是一个”The streaming build system”。直译过来也就是「一个流构建系统」。
以下这段摘自Substack的stream-handbook:
All the different types of stream use
.pipe()
to pair inputs with outputs.
而gulp中正是使用.pipe()
来轻松使用插件配置一系列任务的。
举个例子,我在一个项目种使用了CoffeeScript来书写一些业务代码,然后需要gulp对CoffeeScript进行编译、压缩、合并,那么可见的就有三个任务。
而且可以想到的是这三个任务就是以「流」的方式来运作的,即前者的输出是后者的输入。
示例代码如下:
gulp.task('scripts', function() {
gulp.src(paths.scripts)
.pipe(coffee({bare: true}))
.pipe(uglify())
.pipe(concat('main.min.js'))
.pipe(gulp.dest('dest/js'));
});
上述代码配置了一个任务”scripts”,然后通过gulp.src()
来请求输入的文件,通过.pipe()
将其「运送」到第一个工厂coffee()
,处理完了之后搬运到uglify()
对文件进行压缩,随后则是concat()
来合并上一步的结果,最后通过gulp.dest()
输出到指定目录。
这是我使用gulp感受到的最大的优点。使用.pipe()
让整个处理任务的过程非常清晰,而不用像Grunt中那样繁琐的配置。
实践
昨天下午的时候做了一个小的工具:Base64。简单的来说,这是一个在线的对Base64进行加密和解密,实现从Base64字符串和JSON之间的相互转换的网站。
当然这个工具本身没有什么亮点,不过主要的目的是使用gulp来构建的这个项目,所以可以把它当成是一个使用gulp的实例吧。由于gulp本身就简洁、容易上手,所以这次实践的过程出乎意料的顺利。
我在项目中新建了两个目录:/dest
和/src
,分别是发布文件的目录和源文件的目录。本项目使用的是Sass和CoffeeScript来书写样式和业务逻辑。因此分别需要单独的目录来存放CoffeeScript和Sass的代码,而其对应生成的文件目录为JavaScript和CSS。
这需要我们的task runner以下几个功能:
- 编译CoffeeScript和Sass
- 合并压缩JavaScript文件
- 实时监测文件改动并重复1、2的功能
在明确了目的之后,就可以放肆的在gulp的插件库中寻找自己所需的插件了:
- 编译CoffeeScript: gulp-coffee
- 编译Sass: gulp-ruby-sass
- 压缩JavaScript: gulp-uglify
- 合并JavaScript: gulp-concat
对应JavaScript和CSS,需要分别创建两个流水线进行操作。因此需要声明两个任务:
gulp.task('scripts', function() {
// do some thing
});
gulp.task('sass', function() {
// some thing about sass
});
gulp中整合任务也非常简单,只需要向另一个任务的声明中增加一个参数即可:
gulp.task('default', ['scripts', 'sass'], function() {});
Watch
由于watch的是目录,而且对不同的目录所进行的处理任务是不同的,所以在这里我们就需要两个不同的watch事件来完成我们的需求:
gulp.watch('src/coffee/*.coffee', 'scripts');
gulp.watch('src/sass/*.sass', 'sass');
然后创建一个名为’watch’的task,存放这两个watch事件即可。
关于本次gulp的具体内容可以移步Base64项目的GitHub地址:https://github.com/SFantasy/Base64/。
结语
相信现在Grunt依旧占有着多数Node/前端开发者,但是gulp无疑是Grunt之外另一个(个人感觉)更好的选择。更为简单、快捷,这是gulp的优势所在,而Grunt则坐拥3000+的插件 – 社区生态更为完善。
当然,不论你选择了Grunt还是gulp,task runner并不能帮助你完成更多的任务,所以时间紧凑的话还是更推荐易于上手的gulp。
–EOF–
支持作者 | 文章采用 CC BY-NC-SA 4.0,转载请注明出处