Grunt 一直是前端范畴构建东西(使命运转器也许更正确一些,由于前端构建只是此类东西的一部分用处)的王者,但是它也不是毫无缺点的,近期风头正劲的 gulp.js 隐约有取而代之的态势。那末,终究是什么使得 gulp.js 备受关注呢?
Grunt 之殇
gulp.js 的作者 Eric Schoffstall 在他引见 gulp.js 的 presentation 中总结了 Grunt 的几点不足之处:
插件很难恪守单一义务准绳。由于 Grunt 的 API 设想缺憾,使得很多插件不能不担任一些和其主要使命无关的事变。比如说要对处置惩罚后的文件举行改名操纵,你能够运用的是
uglify
插件,也有能够运用的是concat
插件(取决于事情流的末了一个环节是谁)。我的意见:这也许是个题目,对很多人来讲 Grunt 插件若干存在“职责不明”和“越俎代庖”的状况。在我看来,这也是 Grunt 一个设想头脑:把对文件的操纵笼统为一个自力的组件(Files),任何插件都以雷同的划定规矩来运用它。遗憾在于,运用它的历程发生在每一个插件的自力设置对象里,所以总给人一种“把不应这个插件做的事变丢给它来做”的别扭觉得。
用插件做一些原本不须要插件来做的事变。由于 Grunt 供应了一致的 CLI 进口,子使命由插件定义,由 CLI 敕令来挪用实行,因而哪怕是很简朴的外部敕令(比如说运转
karma start
)都得有一个插件来担任封装它,然后再变成 Grunt CLI 敕令的参数来运转,节外生枝。我的意见:举双手双脚赞同!
试图用设置文件完成一切事,结果就是杂沓不堪。范围较大,构建/分发/布置流程较为复杂的项目,其
Gruntfile
有多复杂置信有阅历的人都有所体味。而 gulp.js 推行的是“写顺序而不是写设置”,它走的是一种 node way。我的意见:关于 node.js 开辟者来讲这是功德,相符他们的一贯作风;不过关于那些纯前端工程师来讲(数目不小),这好像没有什么明显的改良。何况最近 Grunt 社区出现了不少插件来协助开辟者构造/治理/简化痴肥的
Gruntfile
,结果都还不错。所以关于这一点,就见仁见智吧。落伍的流程掌握产生了让人头痛的临时文件/文件夹所致使的机能滞后。这是 gulp.js 下刀子的重点,也是本题目里“流式构建”所处理的根本题目。流式构建改变了底层的流程掌握,大大提高了构建事情的效力和机能,给用户的直观觉得就是:更快。
我的意见:关于流式构建,短短几句话没法讲清它的前因后果,但是在 node.js 的天下里,
streaming
确实是至关重要的。我引荐一份阅读材料:Stream Handbook,读过以后置信内心就有数了。
作为对照和总结,作者列出了 gulp.js 的五大特性:
- 运用 gulp.js,你的构建剧本是代码,而不是设置文件;
- 运用规范库(node.js standard library)来编写剧本;
- 插件都很简朴,只担任完成一件事-基本上都是 20 行摆布的函数;
- 使命都以最大的并发数来实行;
- 输入/输出(I/O)是基于“流式”的。
gulp.js 之道
gulp.js 的官方文档都在 Github 上,本文是一个简介,更详细的细节还请自行阅读文档。在这里我就 gulp.js 的装置和运用流程做一个简述,先一起来明白一下 gulp.js 的风貌吧。
第一步:装置敕令行东西
$ npm install -g gulp
第二步:在你的项面前目今把 gulp 装置为开辟依靠组件(假定你已建立好了 package.json
)
$ cd <YOUR_PROJECT>
$ npm install gulp --save-dev
第三步:在项目的根途径下建立 Gulpfile.js
,初始内容为:
var gulp = require('gulp');
gulp.task('default', function () {
});
第四步:运转!
$ gulp
So far so good! 看起来和 Grunt 没差太远吧?确实云云,gulp.js 的进修曲线照样相称平缓的。接下来,为了能够顺遂的编写构建剧本,我们来进修几个中心的 API 函数——别忧郁,gulp.js 的 API 异常简朴,我们只须要相识四个就足以应对绝大多数的剧本编写了(而且用过 Grunt 的话,这四个都不是什么新鲜货)。
gulp.task(name[, deps], fn)
:注册使命name
是使命称号;deps
是可选的数组,个中列出须要在本使命运转要实行的使命;fn
是使命体,这是 gulp.js 的中心了,须要花时候吃透它,概况见此。gulp.src(globs[, options])
:指明源文件途径
用过 Grunt 的话,globs
肯定不会生疏,这里没什么变化;options
是可选的,详细请检察 gulp.js APIgulp.dest(path)
:指明使命处置惩罚后的目的输出途径gulp.watch(glob[, options], tasks)/gulp.watch(glob[, options, cb])
:看管文件的变化并运转响应的使命。你没看错,watch
作为中心 API 出现在 gulp.js 里了,详细用法照样要多看文档,不过接下来我们会演示简朴的例子。
类型
我们演习一个最常见的类型,写一个 node.js 顺序时所须要的构建剧本。为此我们要做三件事变(括号内列出对应插件的名字,更多插件请到此处寻觅):
- 语法搜检(
gulp-jshint
) - 兼并文件(
gulp-concat
) - 紧缩代码(
gulp-uglify
)
别的,我们能够还须要文件改名操纵,所以 gulp-rename
也会很有效。接着我们须要先在项面前目今装置这些插件:
$ npm install <PLUGIN_NAME> --save-dev
末了我们完成一切使命的编写,完全的代码以下:
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
// 语法搜检
gulp.task('jshint', function () {
return gulp.src('src/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
// 兼并文件以后紧缩代码
gulp.task('minify', function (){
return gulp.src('src/*.js')
.pipe(concat('all.js'))
.pipe(gulp.dest('dist'))
.pipe(uglify())
.pipe(rename('all.min.js'))
.pipe(gulp.dest('dist'));
});
// 看管文件的变化
gulp.task('watch', function () {
gulp.watch('src/*.js', ['jshint', 'minify']);
});
// 注册缺省使命
gulp.task('default', ['jshint', 'minify', 'watch']);
能够看出,基本上一切的使命体都是这么个形式:
gulp.task('使命称号', function () {
return gulp.src('文件')
.pipe(...)
.pipe(...)
// 直到使命的末了一步
.pipe(...);
});
异常轻易明白!猎取要处置惩罚的文件,通报给下一个环节处置惩罚,然后把返回的结果继承通报给下一个环节……直到一切环节完成。pipe
就是 stream
模块里担任通报流数据的要领罢了,至于最最先的 return
则是把全部使命的 stream
对象返回出去,以便使命和使命能够顺次通报实行。
也许写成如许会更直观:
gulp.task('task_name', function () {
var stream = gulp.src('...')
.pipe(...)
.pipe(...)
// 直到使命的末了一步
.pipe(...);
return stream;
});
至此,你已能够运用 gulp.js 完成绝大多数的构建事情了。下一步,我也为你预备了几条发起:
- 花点时候阅读一下 gulp.js 插件库,大抵相识下应用已有的插件你都能够做哪些事变
- 关于经常使用的插件,仔细阅读它们本身的文档,以便发挥出它们最大的功能
- 抽时候进修 gulp.js API,特别是
gulp.task()
里关于使命体的详细描述,学会怎样实行回调函数(callback),怎样返回promise
等等 - 尝试编写合适本身事情流程和习气的使命,假如它事情优越,把它做成插件宣布给人人吧!