[按:网上介绍Gulp和Grunt安装使用的小说很多,甚少相比较二者的思绪,连合法文档都语焉不详。我在此做一个粗陋的相比较,希望能提纲挈领,加深读者对这多个工具的精晓。]

做过一点儿正经开发的同校都精通,构建工具必不可少。C时代的Make、Java的Ant、Ruby的Rake……没有这个工具,两遍遍地点选输入,准烦死你。

在前者和Node
JS的支付中,最普及的构建工具就是Grunt。它的功用说来简单,就是治本一名目繁多的Task。大部分的Task都是第三方的插件,安装好相应的NPM包,再loadNpmTasks就足以用了。

Grunt的部署文件Gruntfile,首要涵盖两局部:

  • 配备每个Task,包括文件从哪个地方,到哪儿去,还有局部处理的选用

  • 团结写一些简便的Task,把第三方插件提供的Task组合起来

别看这几个事情,轻轻松松几百行出来了。每个Task的配置,各有各的规矩,还牵涉到插件间的配合。反正自己从seed库起先做新类型的时候,基本不敢改原来的Gruntfile,很多用不上的效益也搁这儿。留意了瞬间广大开源项目标Gruntfile,也都臃肿杂乱,好不到何地去。

Gruntfile维护起来那么尴尬,有多少个原因:

  • 布局和周转分离
    程序员都晓得,变量的扬言和动用挨在一块儿,最有利清楚和改动。但Gruntfile里,配置Task和调用它们的地方离得很远,极大地扩大了心智负担。

  • 每个插件做的事太多
    每个Task的结果必须写到磁盘文件,另一个Task再读,损害性能倒是小事,更麻烦的是让所有过程变复杂了。
    就像一个个小作坊,来料加工又回去给客户,这当中的联络成本、出错机会都大大扩大。

  • 布局项过多
    行事多了,配置项自然也多。至少输入和出口的地方得配啊。每个插件的部署规则还不尽相同。用每个插件,都得去学习一番。

Gulp应运而生。

也许没几个IT人不明了Unix管道的概念。前顶尖的输出,直接成为后顶级的输入。把大概的工具组合起来,优雅地化解复杂的题目。听起来那么了解呢?是的,Gulp就把这种思维用在构建过程中。

Gulp基于Node
JS的一个体制,叫做stream,有点类似C++中的stream。在Node中,文件访问、输入输出、HTTP连接,都是stream。Gulp的每个插件从stream中读取输入,做一些处理,再出口到stream中。

每个插件不是拿来单独使用的。相反,它小心于完成单一任务。只有把方便的插件组合起来,才能完成具体的Task。引用法定的例证,看看一个独立的Task长什么样(略有删减):

var paths = {
  scripts: ['client/js/**/*.coffee', '!client/external/**/*.coffee']
};

gulp.task('scripts', ['clean'], function() { // 可以依赖于其它task
  return gulp.src(paths.scripts) // 指定输入
      .pipe(coffee()) // 环节一
      .pipe(uglify()) // 环节二
      .pipe(concat('all.min.js')) // 环节三
      .pipe(gulp.dest('build/js')); // 指定输出
});

配置呢?不需要了。是不是天衣无缝,一气浑成?

这我们再回头来看看前边Grunt的几个问题,Gulp是怎么解决的:

  • 配置和运作分离
    code over configuration,直接就在调用的地点安排。

  • 每个插件做的事太多
    单纯任务,依靠组合来发挥功用。就像一条自动化生产线,上一道工序的出现直接提交下一步,功用不要太高。

  • 布置项过多
    既然大家都遵照同一个商事,很多配备就不需要了。

拓宽了看,Gulp像是一个异常贴近领域模型的DSL,而Grunt更像万能的XML。哪个好用,无需多说。在我们制作DSL时,也有参考意义。

最后,举一个Grunt很别扭,Gulp却能优雅解决的例证。

做前端开发会用到一个功能叫usemin。咱们HTML中会引用到无数css和js文件。发表时,这么些文件要合并、压缩、混淆,最终生成一四个文本。为了让修改过的代码绕过浏览器的缓存机制,要按照文件内容hash出文件名。html文件里即将引用这么些新的文件名。

正如一下grunt-usemingulp-usemin个别README的长短,就能看到区别。

grunt.registerTask('build', [
  'useminPrepare', // 准备
  'concat',
  'cssmin',
  'uglify',
  'filerev',
  'usemin' // 执行
]);

grunt-usemin分为两步:

  • 先从html文件中采集需要处理的js和css,传给后续的一堆任务
    它本身并不知道在实际上中会调用哪些其余Task,只好用部分hack,辅助固定的多少个Task。而地点的各种Task,都有和好的安排项。要把这个安排项都列出来,实在太长了。

  • 真的执行,更新html文件里的js和css引用。

gulp-usemin就彻底得多,没有丝毫盈余的东西:

gulp.task('usemin', function() {
  gulp.src('./*.html')
    .pipe(usemin({
      css: [minifyCss(), 'concat'],
      html: [minifyHtml({empty: true})],
      js: [uglify(), rev()]
    }))
    .pipe(gulp.dest('build/'));
});

usemin不需要有minifyCssminifyHtmluglifyrev那个插件的别样文化,只要把相应的情节从stream丢出去就好。在用那多少个插件组装task时才需要关爱。

时下,Gulp的社区还远不如Grunt成熟,有些功用的插件,Gulp可能就从未有过。这其实不算很大的劣势,只要丰富好用,追上来很快。而且,写一个Gulp插件要比相应的Grunt插件短小得多!

相关文章

网站地图xml地图