Gulp挑衅Grunt,背后的工学

[按:网上介绍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插件短小得多!

相关文章