You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
vardefaults=require('lodash.defaults');varthrough=require('through2');vargs=require('glob-stream');varFile=require('vinyl');// 省略非重要代码若干行functionsrc(glob,opt){// 继续省略代码varglobStream=gs.create(glob,options);// when people write to use just pass it throughvaroutputStream=globStream.pipe(through.obj(createFile)).pipe(getStats(options));if(options.read!==false){outputStream=outputStream.pipe(getContents(options));}// 就是这里了returnoutputStream.pipe(through.obj());}
varthrough2=require('through2');varCombine=require('ordered-read-streams');varunique=require('unique-stream');varglob=require('glob');varminimatch=require('minimatch');varglob2base=require('glob2base');varpath=require('path');// 必须省略很多代码// create 方法
create: function(globs,opt){// 继续省略代码// create all individual streamsvarstreams=positives.map(function(glob){returngs.createStream(glob,negatives,opt);});// then just pipe them to a single unique stream and return itvaraggregate=newCombine(streams);varuniqueStream=unique('path');// TODO: set up streaming queue so items come in orderreturnaggregate.pipe(uniqueStream);
functionOrderedStreams(streams,options){if(!(thisinstanceof(OrderedStreams))){returnnewOrderedStreams(streams,options);}streams=streams||[];options=options||{};if(!Array.isArray(streams)){streams=[streams];}options.objectMode=true;Readable.call(this,options);// stream data bufferthis._buffs=[];if(streams.length===0){this.push(null);// no streams, closereturn;}streams.forEach(function(s,i){if(!s.readable){thrownewError('All input streams must be readable');}s.on('error',function(e){this.emit('error',e);}.bind(this));varbuff=[];this._buffs.push(buff);s.on('data',buff.unshift.bind(buff));s.on('end',flushStreamAtIndex.bind(this,i));},this);}
写在前面
本来是想写个如何编写gulp插件的科普文的,突然探究欲又发作了,于是就有了这篇东西。。。翻了下源码看了下
gulp.src()
的实现,不禁由衷感慨:肿么这么复杂。。。进入正题
首先我们看下
gulpfile
里面的内容是长什么样子的,很有express中间件的味道是不是~我们知道
.pipe()
是典型的流式操作的API。很自然的,我们会想到gulp.src()
这个API返回的应该是个Stream对象(也许经过层层封装)。本着一探究竟的目的,花了点时间把gulp的源码大致扫了下,终于找到了答案。gulpfile.js
提前剧透
此处有内容剧透,如有对剧透不适者,请自行跳过本段落。。。
探究之路
首先,我们看下
require('gulp')
返回了什么。从gulp的源码来看,返回了Gulp
对象,该对象上有src
、pipe
、dest
等方法。很好,找到了我们想要的src
方法。接着往下看参考:https://github.com/gulpjs/gulp/blob/master/index.js#L62
gulp/index.js
从下面的代码可以看到,
gulp.src
方法,实际上是vfs.src
。继续参考:https://github.com/gulpjs/gulp/blob/master/index.js#L25
gulp/index.js
接下来我们看下
vfs.src
这个方法。从vinyl-fs/index.js
可以看到,vfs.src
实际是vinyl-fs/lib/src/index.js
。参考:https://github.com/wearefractal/vinyl-fs/blob/master/index.js
vinyl-fs/index.js
那么,我们看下
vinyl-fs/lib/src/index.js
。可以看到,gulp.src()
返回的,实际是outputStream
这货,而outputStream
是gs.create(glob, options).pipe()
获得的,差不多接近真相了,还有几步而已。参考:https://github.com/wearefractal/vinyl-fs/blob/master/lib/src/index.js#L37
vinyl-fs/lib/src/index.js
我们再看看
glob-stream/index.js
里的create
方法,最后的return aggregate.pipe(uniqueStream);
。好的,下一步就是真相了,我们去ordered-read-streams
这个项目一探究竟。参考:https://github.com/wearefractal/glob-stream/blob/master/index.js#L89
glob-stream/index.js
真相来了,我们看下
ordered-read-streams
的代码,可能刚开始看不是很懂,没关系,知道它实现了自己的Stream
就可以了(nodejs是有暴露相应的API让开发者对Stream进行定制的),具体可参考:http://www.nodejs.org/api/stream.html#stream_api_for_stream_implementors代码来自:https://github.com/armed/ordered-read-streams/blob/master/index.js
ordered-read-streams/index.js
参考:https://github.com/armed/ordered-read-streams/blob/master/index.js
写在后面
兜兜转转一大圈,终于找到了
gulp.src()
的源头,大致流程如下,算是蛮深的层级。代码细节神马的,有兴趣的同学可以深究一下。The text was updated successfully, but these errors were encountered: