居尔p挑衅Grunt,背后的文学

[按:网上介绍居尔p和Grunt安装使用的篇章很多,甚少相比较贰者的笔触,连合法文书档案都语焉不详。笔者在此做3个粗陋的相比较,希望能言简意赅,加深读者对这多个工具的知晓。]

做过简单正经开发的同班都精通,创设筑工程具不可缺少。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再读,损害品质倒是小事,更麻烦的是让1切进程变复杂了。
    就像3个个小作坊,来料加工又回到给客户,那中间的联络开支、出错机会都大大扩大。

  • 布局项过多
    工作多了,配置项自然也多。至少输入和出口的岗位得配啊。每种插件的安顿规则还互不相同。用各种插件,都得去学学1番。

居尔p应运而生。

只怕没多少个IT人不领悟Unix管道的定义。前一流的出口,直接变成后一流的输入。把简单的工具组合起来,优雅地缓解复杂的难题。听起来那么熟识呢?是的,居尔p就把那种考虑用在营造进程中。

居尔p基于Node
JS的二个机制,叫做stream,有点类似C++中的stream。在Node中,文件访问、输入输出、HTTP连接,都以stream。居尔p的种种插件从stream中读取输入,做壹些处理,再出口到stream中。

种种插件不是拿来单独运用的。相反,它小心于实现单1任务。只有把适用的插件组合起来,才能一鼓作气具体的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的多少个难题,居尔p是怎么化解的:

  • 配备和平运动转分离
    code over configuration,直接就在调用的地点布署。

  • 种种插件做的事太多
    单纯性职务,依靠组合来发挥作用。仿佛一条自动化生产线,上1道工序的产出直接交给下一步,功能不要太高。

  • 配备项过多
    既然大家都依据同1个商议,很多布局就不须求了。

加大了看,居尔p像是贰个越发靠近领域模型的DSL,而Grunt更像万能的XML。哪个好用,无需多说。在大家制作DSL时,也有参照意义。

末尾,举1个Grunt很别扭,居尔p却能优雅化解的例子。

做前端开发会用到贰个效果叫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时才须要关心。

当下,居尔p的社区还远不比Grunt成熟,有个别作用的插件,居尔p大概就从未。那实际不算一点都不小的劣势,只要丰富好用,追上来十分的快。而且,写三个Gulp插件要比相应的Grunt插件短小得多!