做者:Jogis
原文连接:https://github.com/yesvods/Blog/issues/1
转载请注明原文连接以及做者信息css
提到 Gulp,不得不说到的是较早的 JS 项目自动化构建工具——Grunt。前端
前端开发过程当中,特别是最近几年多了 CoffeeScript、Sass、Less 等一些预编译语言,不少代码每次写完须要手动到工做目录去编译才能执行。此外,项目预发布时候须要进行 js、css 文件合并、压缩、重命名等操做,实在是很繁琐。此前不少工程师使用的是 Makefile 构建项目,可是这要求须要必定Linux基础,并且编写配置文件会增大很是多工做量, Grunt 的出现,解放了前端工程师的双手=_=node
Grunt 经过 CLI 配合配置文件 gruntfile.js 去完成自动化构建任务,社区有很是多的 Grunt 插件,好比 concat(合并文件)、 uglify(js压缩),只须要在 gruntfile.js 中配置好路径等一些参数,运行如下命令就能够自动执行。c++
grunt takeName
Gulp是一款 The streaming build system(流式构建系统),若是说 Grunt 是基于 gruntfile.js 任务执行器,Gulp 就是基于 NodeJS 的文件流任务执行器,比起 Grunt 有以下特色git
使用方便
经过代码优于配置的策略,Gulp 可让简单的任务简单,复杂的任务更可管理。github
构建快速
经过流式操做,减小频繁的 IO 操做,更快地构建项目。npm
插件高质
Gulp 有严格的插件指导策略,确保插件能简单高质的工做。gulp
易于学习
少许的API,掌握 Gulp 能够绝不费力。构建就像流管道同样,轻松加愉快。promise
Gulp 主要 API 为 gulp.src(使用glob模式匹配得到文件流集)、gulp.dest(输出gulp文件流集到指定路径,路径指定相对于gulpfile.js配置文件)、gulp.watch(监听glob模式匹配的文件集,有改动时执行相应gulp任务),如图:浏览器
译做管弦乐演奏家,大多数就是一个老头拿着个小棍的形象,就像这样:
一个npmjs模块,就是一个以最大并发方式去排序或执行一系列的任务。这些任务就是咱们以后会用到的 Gulp 任务,好比说 css 命名的任务,里面包括css的浏览器前缀添加、合并、压缩等操做。orchestrator 经过实例化一个对象,在对象上调用 add 来添加特定命名的任务、添加任务时候能够声明任务依赖,好比:
var Orchestrator = require('orchestrator'); var orchestrator = new Orchestrator(); orchestrator.add('thing1', function(){ // do stuff }); orchestrator.add('thing2', function(){ // do stuff }); orchestrator.add('mytask', ['thing1','thing2'], function() { // Do stuff });
以上代码,添加了3个 Gulp 任务,mytask 任务依赖于 thing1 和 thing2 ,即必须执行完后面两个任务,mytask才能执行,经过任务依赖,很容易理清和构建任务时候的执行顺序。须要注意的是,在填写 do stuff 时候,要确保其返回一个 promise 或者是 event stream(最经常使用),好比一个简单的任务是这样定义的:
var map = require('map-stream'); orchestrator.add('thing4', function(){ var stream = map(function (args, cb) { cb(null, args); }); // do stream stuff return stream; });
或则是返回一个 promise:
var Q = require('q'); orchestrator.add('thing3', function(){ var deferred = Q.defer(); // do async stuff setTimeout(function () { deferred.resolve(); }, 1); return deferred.promise; });
orchestrator 调用 start 来执行特定名称的任务,可一次执行多个:
orchestrator.start('one', 'two');
以上两个是 orchestrator 最经常使用的用于实现 Gulp 的函数,除此以外,还有任务检测,任务暂停,任务事件监听,想详细了解可访问npmjs:https://www.npmjs.org/package/orchestrator
这是 Gulp 采用的一个虚拟文件系统,能够读取 glob 模式匹配到的文件并转成文件流,能够获取文件流并转成文件集。其中 vinyl-fs 使用 vinyl 虚拟文件描述类,来对 glob 匹配到的文件进行描述,所谓的描述,只是简单的文件名与路径,以及文件内容,能够说是一个文件的封装,能够看看 vinyl 是如何描述一个或一组文件的:
var File = require('vinyl'); var coffeeFile = new File({ cwd: "/", base: "/test/", path: "/test/file.coffee", contents: new Buffer("test = 123") });
除了 vinyl ,vinyl-fs 还须要依赖 glob-stream 读写文件流,如图:
你们可能有疑问,读写文件流,为何不用 nodejs 内核的 steam 类来读写呢,骚安勿燥,Gulp 既然是基于 nodejs 构建,最终天然也是依赖 nodejs 内核实现它的功能的。
只是,stream 类读取文件流只针对一个文件路径,glob-stream 就是实现从获取 glob 模式匹配文件集,到转换成文件路径,再到读取,仍是有一段距离的。如图:
glob-stream 经过 minimatch 来进行 glob 模式匹配,经过其余路径模块,得到一组文件路径,而后就是 ordered-read-streams 发光发热时候啦,对这组文件路径一个个地读啊,而后就得到一组文件流啦。
好啦,终于分析完 Gulp 的实现,经过对其中模块的阅读,其实 Nodejs 模块有点像乐高积木,内核给出的就是最基本的积木啦,不过你能够无限次使用它们,来堆出一个个小的物体,经过小小的物体组合,来组成很是徇丽多姿的乐高做品啦~
固然,也是有一些 c++ 实现的nodejs模块,主要是用于一些须要高性能运算的地方,不过npmjs.org上介绍到的模块,大部分的依赖都是基于 nodejs 内核实现滴。