gulp源码简介

gulp源码核心部分寥寥60+行。但是通过这60+行代码,gulp给我们带来的确是前端自动化构建的便利。以往以为其源码肯定蛮复杂,
却没想到却是这么60+行,这60+行的背后,是来自于模块化的支撑。

gulp的四个接口分别来源于orchestrator,vinyl-fs两个模块。
所以gulp的所有特性都来自于这两个模块。
Orchestrator是用来任务管理,以及发布一些事件,vinyl-fs 则提供代表gulp灵魂的流式文件系统。
研究清楚了这两个模块,也就了解了gulp。

  • gulp.task = Gulp.prototype.task = Gulp.prototype.add;

  • Gulp.prototype.src = vfs.src;

  • Gulp.prototype.dest = vfs.dest;

  • Gulp.prototype.watch = function(glob, opt, fn) { ... return vfs.watch(glob, opt, fn);};

同时gulp本身是直接继承于Orchestrator模块。

function Gulp() {Orchestrator.call(this);  // gulp直接继承于Orchestrator模块
}

orchestrator模块介绍

A module for sequencing and executing tasks and dependencies in maximum concurrency

译:以最大并发能力顺序执行任务与其依赖的一个功能模块

var Orchestrator = function () {EventEmitter.call(this); //继承了EventEmitter对象this.doneCallback = undefined; // 当task里所有的任务完成时调用这个函数this.seq = []; // task以及task里依赖的执行顺序,(start里会有多个task,每个task又有可能有多个依赖,每个依赖又可能有多个依赖,所以需要保存其执行顺序)this.tasks = {}; // 任务对象,包括任务名,依赖,回调函数this.isRunning = false; // 表示当前是否在执行任务
};

Orchestrator利用seq这个队列数组存储需要执行的task,这样如果计算机有能力执行,它就从队列里取走一个,如果还有能力就再取走一个,
所以这其实是in maximum concurrency即以最大的并发能力来执行。

关于seq的构造,则是引入sequencify模块递归计算其依赖并压入队列。

同时通过继承EventEmitter对象,Orchestrator发布了一些列可订阅的事件,用于插件以及命令行里的gulp在事件发生时输出相应的信息。

`var events = ['start','stop','err','task_start','task_stop',
'task_err','task_not_found','task_recursion'];`

系统暴露了这些事件以供插件调用,并且提供了2个方法

  • listenToEvent是监听某一个事件

  • onAll是不管events里的那个就监听

vinyl-fs模块介绍

主要依赖于vinyl与glob-watcher。后者提供监视文件变化的watch接口,
前者则在file的基础上封装一些属性与方法,构造出独特的vinyl文件对象。
Gulp使用的是Stream,但却不是普通的Node Stream,而是基于vinyl对象的vinyl File Object Stream

构造函数如下

function File(file) {if (!file) file = {};// 保存该文件的路径变化记录var history = file.path ? [file.path] : file.history;this.history = history || [];this.cwd = file.cwd || process.cwd(); // 当前文件所在目录,即current work directorythis.base = file.base || this.cwd; // 用于相对路径,代表根目录this.stat = file.stat || null; // 使用 fs.Stats得到的结果this.contents = file.contents || null; // 文件内容this._isVinyl = true; // 文件对象是否是vinyl对象,vinyl对象即对file对象封装后的结果
}

Gulp为什么不使用普通的Node Stream呢?

普通的Node Stream只传输String或Buffer类型,也就是只关注内容。但Gulp不只用到了文件的内容,而且还用到了这个文件的相关信息(比如路径)。

因此,Gulp的Stream是Object风格的,也就是Vinyl File Object了。所以需要有有contents、path这样的多个属性了。

写在末尾

阅读gulp代码的这一次,是我第一次阅读这种开源的模块化项目。深深的被震撼到了,认识到了模块化的巨大力量。正如7层计算级机网络模型。
将层级抽象出来,每一层只需要关注自己那一层的事情,直接调用下一层提供的API。就能完成非常复杂的事情,而不需要凡是亲力亲为,一行行
代码,一个个小问题依次解决。能够解放双手做更多的事情。

参考文档

  1. 探究Gulp的Stream

  2. 从零单排之gulp实战

  3. 开源Nodejs项目推荐gulp核心模块:Orchestrator

WilsonLiu's blog首发地址:http://blog.wilsonliu.cn

阅读gulp源码小结相关推荐

  1. 阅读react-redux源码(五) - connectAdvanced中store改变的事件转发、ref的处理和pure模式的处理

    阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 阅读react-redux源 ...

  2. 阅读react-redux源码(三) - mapStateToPropsFactories、mapDispatchToPropsFactories和mergePropsFactories

    阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 阅读react-redux源 ...

  3. 阅读react-redux源码 - 一

    阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 阅读react-redux源 ...

  4. 阅读react-redux源码 - 零

    阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 react的技术栈一定会遇到 ...

  5. 如何高效、优雅、愉快地阅读项目源码?

    代码是形式,逻辑是神韵. 引子 本文探索如何阅读成熟框架的源码. 温馨提示 欲速则不达.阅读源码很容易理解为就是直接去阅读代码本身.实际上,代码只是形式,逻辑才是神韵. 凡是有助于去理解逻辑,理解其原 ...

  6. 逐行阅读redux源码(二)combineReducers

    前情提要 逐行阅读redux源码(一)createStore 认识reducers 在我们开始学习源码之前,我们不妨先来看看何谓reducers: 如图所见,我们可以明白, reducer 是用来对初 ...

  7. C++Primer Plus (第六版)阅读笔记 + 源码分析【目录汇总】

    C++Primer Plus (第六版)阅读笔记 + 源码分析[第一章:预备知识] C++Primer Plus (第六版)阅读笔记 + 源码分析[第二章:开始学习C++] C++Primer Plu ...

  8. webuploader 怎么在react中_另辟蹊径搭建阅读React源码调试环境支持所有React版本细分文件断点调试...

    引言(为什么写这篇文章) 若要高效阅读和理解React源码,搭建调试环境是必不可少的一步.而常规方法:使用react.development.js和react-dom.development.js调试 ...

  9. 阅读react-redux源码(七) - 实现一个react-redux

    阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 阅读react-redux源 ...

最新文章

  1. Linux之切换目录命令
  2. 【Elastic Stack学习】ELK日志分析平台(一)ELK简介、ElasticSearch集群
  3. 直播预告丨企服企业如何科学搭建规模化获客体系?
  4. linux下的bc计算器设置scale精度
  5. C++ 指向类成员的指针
  6. [html] 如何在不同的端口间共享cookie?
  7. 常用的五种大数据分析方法
  8. 如何用ROS和爱快来组建网络,实现单机单IP(转载)
  9. 【原生JavaScript案例】原生JS实现进度条
  10. IDEA 导入项目中文注释乱码解决
  11. 算法设计与分析——分支限界法——布线问题
  12. 怎样彻底卸载电脑上的软件
  13. JavaSE就业班四----数据库Oracle和JDBC
  14. dismiss和remove_eliminate, remove, dismiss的区别:新东方考研英语词汇辨析
  15. 浩辰cad2019破解补丁|浩辰cad2019无限试用破解补丁下载(附浩辰cad2019激活工具/无需激活码)
  16. android之父:安迪*鲁宾
  17. python如何连redis_Python连接Redis的基本配置方法
  18. 勤学修身 放飞梦想4
  19. 什么是jQuery,jquery的特点
  20. 十二、案例:加利福尼亚房屋价值数据集(多元线性回归) Lasso 岭回归 分箱处理非线性问题 多项式回归

热门文章

  1. 寻找中项和第k小元素c语言,分治法第k小元素poj2104.ppt
  2. 根据概率分布随机采样python_PR Sampling Ⅱ:马尔可夫链蒙特卡洛 MCMC及python实现...
  3. python期末复习卷_【期末复习卷A】六年级科学上册期末复习试题
  4. php布尔类型代码,PHP数据类型之布尔型的介绍
  5. 云南大学软件学院计算机网络实验三,云南大学 软件学院 计网实验5
  6. idea ssm框架搭建详细步骤_搭建一套纯净版的SSM框架,随时CV使用它不香吗?
  7. android 检查 write_external_storage,android – 如何知道何时需要WRITE_EXTERNAL_STORAGE
  8. python sqlite connection
  9. CVE-2020-16875:Microsoft Exchange RCE复现
  10. 阿里架构总监一次讲透中台架构,13页PPT精华详解,建议收藏