gulp.src()内部实现探究
写在前面
本来是想写个如何编写gulp插件的科普文的,突然探究欲又发作了,于是就有了这篇东西。。。翻了下源码看了下gulp.src()
的实现,不禁由衷感慨:肿么这么复杂。。。
进入正题
首先我们看下gulpfile
里面的内容是长什么样子的,很有express中间件的味道是不是~
我们知道.pipe()
是典型的流式操作的API。很自然的,我们会想到gulp.src()
这个API返回的应该是个Stream对象(也许经过层层封装)。本着一探究竟的目的,花了点时间把gulp的源码大致扫了下,终于找到了答案。
gulpfile.js
var gulp = require('gulp'),
preprocess = require('gulp-preprocess'); gulp.task('default', function() { gulp.src('src/index.html')
.pipe(preprocess({USERNAME:'程序猿小卡'}))
.pipe(gulp.dest('dest/'));
});
提前剧透
此处有内容剧透,如有对剧透不适者,请自行跳过本段落。。。
gulp.src() 的确返回了定制化的Stream对象。可以在github上搜索
ordered-read-streams
这个项目。大致关系是:
ordered-read-streams --> glob-stream --> vinyl-fs --> gulp.src()
探究之路
首先,我们看下require('gulp')
返回了什么。从gulp的源码来看,返回了Gulp
对象,该对象上有src
、pipe
、dest
等方法。很好,找到了我们想要的src
方法。接着往下看
参考:https://github.com/gulpjs/gulp/blob/master/index.js#L62
gulp/index.js
var inst = new Gulp();
module.exports = inst;
从下面的代码可以看到,gulp.src
方法,实际上是vfs.src
。继续
参考:https://github.com/gulpjs/gulp/blob/master/index.js#L25
gulp/index.js
var vfs = require('vinyl-fs');
// 省略很多行代码
Gulp.prototype.src = vfs.src;
接下来我们看下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
'use strict'; module.exports = {
src: require('./lib/src'),
dest: require('./lib/dest'),
watch: require('glob-watcher')
};
那么,我们看下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
var defaults = require('lodash.defaults');
var through = require('through2');
var gs = require('glob-stream');
var File = require('vinyl'); // 省略非重要代码若干行 function src(glob, opt) {
// 继续省略代码 var globStream = gs.create(glob, options); // when people write to use just pass it through
var outputStream = globStream
.pipe(through.obj(createFile))
.pipe(getStats(options)); if (options.read !== false) {
outputStream = outputStream
.pipe(getContents(options));
}
// 就是这里了
return outputStream
.pipe(through.obj());
}
我们再看看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
var through2 = require('through2');
var Combine = require('ordered-read-streams');
var unique = require('unique-stream'); var glob = require('glob');
var minimatch = require('minimatch');
var glob2base = require('glob2base');
var path = require('path'); // 必须省略很多代码 // create 方法
create: function(globs, opt) {
// 继续省略代码
// create all individual streams
var streams = positives.map(function(glob){
return gs.createStream(glob, negatives, opt);
}); // then just pipe them to a single unique stream and return it
var aggregate = new Combine(streams);
var uniqueStream = unique('path'); // TODO: set up streaming queue so items come in order return aggregate.pipe(uniqueStream);
真相来了,我们看下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
function OrderedStreams(streams, options) {
if (!(this instanceof(OrderedStreams))) {
return new OrderedStreams(streams, options);
} streams = streams || [];
options = options || {}; if (!Array.isArray(streams)) {
streams = [streams];
} options.objectMode = true; Readable.call(this, options); // stream data buffer
this._buffs = []; if (streams.length === 0) {
this.push(null); // no streams, close
return;
} streams.forEach(function (s, i) {
if (!s.readable) {
throw new Error('All input streams must be readable');
}
s.on('error', function (e) {
this.emit('error', e);
}.bind(this)); var buff = [];
this._buffs.push(buff); s.on('data', buff.unshift.bind(buff));
s.on('end', flushStreamAtIndex.bind(this, i));
}, this);
}
参考:https://github.com/armed/ordered-read-streams/blob/master/index.js
写在后面
兜兜转转一大圈,终于找到了gulp.src()
的源头,大致流程如下,算是蛮深的层级。代码细节神马的,有兴趣的同学可以深究一下。
ordered-read-streams --> glob-stream --> vinyl-fs --> gulp.src()
gulp.src()内部实现探究的更多相关文章
- 温故而知新 gulp.src 指定数组文件夹
gulp.src语法是基于这个库来实现的,所以详情请看这个API: https://www.gulpjs.com.cn/docs/api/ https://github.com/isaacs/node ...
- Gulp:插件编写入门
之前挖了个坑,准备写篇gulp插件编写入门的科普文,之后迟迟没有动笔,因为不知道该肿么讲清楚Stream这货,毕竟,gulp插件的实现不像grunt插件的实现那么直观. 好吧,于是决定单刀直入了.文中 ...
- Gulp探究折腾之路(I)
前言: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成:使用她,我们不仅可以很愉快的编写代码 ...
- Gulp探究折腾之路(I)2
文/晚晴幽草(简书作者)原文链接:http://www.jianshu.com/p/9768a4dc7cf7著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 前言: gulp是前端开发过 ...
- gulp 编译es6 探究
1.gulp配置: var gulp = require('gulp') var fs = require("fs") var babelify = require('babeli ...
- 如何写一个能在gulp build pipe中任意更改src内容的函数
gulp在前端自动化构建中非常好用,有非常丰富的可以直接拿来使用的plugin,完成我们日常构建工作. 但是万事没有十全十美能够完全满足自己的需求,这时我们就要自己动手写一个小的函数,用于在gulp ...
- gulp思考
Gulp,一个基于流的构建工具. 这是自己写的一个构建的demo,只是一个纯演示的示例,并没有完成什么项目工作.下面根据这个demo介绍一下Gulp. 上代码: gulpfile.js 'use st ...
- 前端构建工具之争——Webpack vs Gulp 谁会被拍死在沙滩上
.table tr>td:nth-child(1){width: 2em !important;padding-left: .6rem !important;padding-right: .6r ...
- Gulp介绍与入门实践
Gulp,一个基于流的构建工具. 这是自己写的一个构建的demo,只是一个纯演示的示例,并没有完成什么项目工作.下面根据这个demo介绍一下Gulp. 上代码: gulpfile.js 'use st ...
随机推荐
- Jmeter之HTTP Cookie 管理器
Jmeter所支持的Cookie标准有很多,同时jmeter也提供两组程序实现这些cookie标准,分别是httpclient3与httpclient4.http cookie 管理器中的Implem ...
- jQuery中使用attribute,prop获取,设置input的checked值【转】
1.prop方法获取.设置checked属性 当input控件checkbox设置了checked属性时,无论checked=”“或 checked=”checked”,$(obj).prop(“ch ...
- CSS| background_属性总结
Property List 属性 描述 CSS background 在一个声明中设置所有的背景属性. 1 background-attachment 设置背景图像是否固定或者随着页面的其余部分滚动. ...
- TMOUT优化终端超时
有时候,管理员终端登陆了系统,如果离开没有退出账户,则会有安全隐患存在,因此需要优化终端超时. 设置终端超时: export TMOUT=10 永久生效: echo "export TMOU ...
- fedora27安装谷歌浏览器Chrome
安装 添加chrome源 #cd /etc/yum.repos.d #wget http://repo.fdzh.org/chrome/google-chrome-mirrors.repo 安装Chr ...
- 高斯消去、追赶法 matlab
1. 分别用Gauss消去法.列主元Gauss消去法.三角分解方法求解方程组 程序: (1)Guess消去法: function x=GaussXQByOrder(A,b) %Gauss消去法 N = ...
- 【优质】React的学习资源
React的学习资源 github 地址: https://github.com/LeuisKen/react-collection https://github.com/reactnativecn/ ...
- 何为用户体验?附《用户体验的要素》PDF版下载
一.什么是用户体验? 用户体验(User Experience,简称UE/UX)是用户在使用产品过程中建立起来的一种纯主观感受.但是对于一个界定明确的用户群体来讲,其用户体验的共性是能够经由良好设计实 ...
- AlloyDesigner 使用
前端开发视觉是很重要的一部分,所以视觉的还原度很重要,今天给大家介绍一个很好用的视觉精度调整插件 一.下载AlloyDesigner插件 下载插件 二.保存视觉稿为图片格式 1.psd 用ps直接保存 ...
- js指定范围随机整数
js获取指定范围内随机整数,例如 6-10 (m-n) 计算公式: Math.floor(Math.random()*(n-m))+m // 6-10随机数,用循环得出一组测试随机数 var str ...