Webpack4.0各个击破(8)tapable篇
一. tapable概述
tapable地址:【tapable-0.2】
tapable是webpack的核心框架(4.0以上版本的API已经发生了变化),是一个基于事件流的框架,或者叫做发布订阅模式,或观察者模式,webpack的整个生命周期及其开放的自定义插件系统都离不开tapable的支持,研究其运行原理是阅读webpack源代码的第一步。官方仓库master分支的代码是经过ES6重构的,模块化拆分非常细,且加入了很多非核心逻辑,阅读难度较大。建议先从官方仓库中0.2版本的分支开始学习,整个源码只有400行,相对容易理解。
二. tapable-0.2源码解析
2.1 代码结构
//类定义
function Tapable() {
this._plugins = {};
}
//模块导出
module.exports = Tapable;
//定义了许多内部方法和原型方法
...
Tapable实际上就是一个类定义的模块。
2.2 事件监听方法
tapable通过原型方法Tapable.prototype.plugin来注册事件监听。

这段代码并不复杂,调用plugin方法来注册一个事件,参考浏览器环境中的addEventListener()方法就很容易理解了。其逻辑就是将回调函数按照事件名称进行归类存储,在tapable实例中统一调度管理。
//__plugin属性上挂载了各个注册事件的回调函数
tapable.__plugins = {
'click':[fn1, fn2, fn3],
'mousedown':[fn21,fn22,fn23]
...
}
2.3 事件触发方法
tapable提供了许多事件触发的方式,其基本功能可以参考浏览器环境中的dispatchEvent( )。
tapable中的事件触发方式可以按命名分为如下几个大组:
- waterfall方法会将上一个监听的执行结果传给下一个
- bailResult方法只会执行到第一个返回结果不是undefined的监听器
- Series方法会线性执行异步监听器,上一个结束后下一个才会开始
- Parallel方法会并行执行所有异步监听
tapable中的典型方法如下:
Tapable.prototype.applyPlugins( )

同步方法,该方法接受任意参数,以第一个参数为事件名查找监听器数组,依次执行监听器的apply( )方法,触发时将调用时除名称以外的其他参数传入apply( )方法。
Tapable.prototype.applyPluginsWaterfall( )

同步方法,该方法接受任意参数,如果指定事件没有注册监听器,则返回第二个参数(init),否则依次执行监听器的apply( )方法,传入的args是前一个执行前一个监听器apply( )方法的返回值。瀑布流这个方法名很形象。
Tapable.prototype.applyPluginsBailResult( )

同步方法,该方法接受任意参数,依次执行监听器的apply( )方法并取得返回值,直到某个apply( )返回一个不为undefined的结果,则停止执行并将这个结果返回。
Tapable.prototype.applyPluginsAsync( )

异步执行监听回调的方法。这个方法是顺序执行,等到第一个插件执行结束后才会执行下一个插件,实现的方式就是将下一个插件当做回调函数传入第一个插件,在第一个插件的apply( )方法的方法体最后(或是异步方法最后)来调用下一个监听插件的执行。这里利用闭包实现了一个迭代器,变量记录在applyPluginsAsync( )方法中(就是变量i),并在回调中函数next( )中保持了对i的引用。
例如需要用applyPluginsAsync( )方法执行的插件需要在apply方法中显式执行回调函数:
class Plugin1{
apply(info){
var callback = Array.prototype.pop.call(arguments[1]);
//这里取到的callback,实际上就是源码中的具名函数next()
callback();
}
}
其他的异步方法大同小异,不再赘述。
源码的异步方法定义中使用copyProperties( )来处理两个函数,笔者尝试了很多情况这个方法都并未执行,实际情况就是将next函数加入了参数数组并继续执行,希望对此有研究的读者能够点明一下。
三. tapable1.0概述
tapable地址:【tapable-1.0】
tapable在1.0版本做了很大改进,使用ES6语法重写了整个框架,除了更换了API外,在插件定义方面进行了明显升级,原来只通过plugin( )方法来定义插件,不阅读源码很难知道插件的规范格式,新版本的tapable提供了基本样例,细分的事件钩子(*Hook),新的触发事件的方法(tap,tapAsync,tapPromise)等等,但实现的基本需求是一致的,感兴趣的读者可以自行学习。
作者:大史不说话
链接:Webpack4.0各个击破(8)tapable篇
来源:博客园
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Webpack4.0各个击破(8)tapable篇的更多相关文章
- webpack4.0各个击破(7)—— plugin篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- Webpack4.0各个击破(7)plugin篇
目录 一. plugin概述 1.1 Plugin的作用 1.2 Compiler 1.3 Compilation 二. 如何写一个plugin 四. 实战 [参考] 一. plugin概述 1.1 ...
- webpack4.0各个击破(5)—— Module篇
webpack4.0各个击破(5)-- Module篇 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决 ...
- Webpack4.0各个击破(10)integration篇
一. Integration 下文摘自webpack中文网: 首先我们要消除一个常见的误解,webpack是一个模块打包工具(module bundler),它不是一个任务执行工具,任务执行器是用来自 ...
- Webpack4.0各个击破(6)loader篇
目录 一. loader综述 二. 如何写一个loader 三. loader的编译器本质 [参考] 一. loader综述 loader是webpack的核心概念之一,它的基本工作流是将一个文件以字 ...
- Webpack4.0各个击破(5)module篇
一. 模块化乱炖 脚本合并是基于模块化规范的,javascript模块化是一个非常混乱的话题,各种[*MD]规范乱飞还要外加一堆[*.js]的规范实现.现代化前端项目多基于框架进行开发,较为流行的框架 ...
- Webpack4.0各个击破(1)html篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- webpack4.0各个击破(4)—— Javascript & splitChunk
目录 一. Js模块化开发 二. Js文件的一般打包需求 三. 使用webpack处理js文件 3.1 使用babel转换ES6+语法 3.2 脚本合并 3.3 公共模块识别 3.4 代码分割 3.5 ...
- webpack4.0各个击破(8)—— tapable篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
随机推荐
- Redis基础篇(五)AOF与RDB比较和选择策略
RDB和AOF对比 关于RDB和AOF的优缺点,官网上面也给了比较详细的说明redis.io/topics/pers- RDB 优点: RDB快照是一个压缩过的非常紧凑的文件,保存着某个时间点的数据集 ...
- 解决在Filter中读取Request中的流后, 然后再Control中读取不到的做法
摘要: 大家知道, StringMVC中@RequestBody是读取的流的方式, 如果在之前有读取过流后, 发现就没有了. 我们来看一下核心代码: filter中主要做的事情, 就是来校验请求是否合 ...
- junit 测试用例多并发
最近再用测试用例写个多并发,但是测试用例一运行完程序就结束啦.还没有等到多线程运行完.这个时候可以用断点在多线程后面停住或者让主线程睡眠多一些
- CentOS 8 安装Nginx
安装命令: dnf install nginx -y 这就安装完成了 ,对你没看错一个命令就已经把nginx安装好了,不信你通过 nginx -V 命令查看. 常用操作: 1.nginx配置文件目录 ...
- 设计模式——从HttpServletRequestWrapper了解装饰者模式
从一个业务开始 最近项目上紧急需要,为了应付一个不知道啥的安全检测,我们要给系统追加防XSS注入的功能,这里有经验的JavaWeb开发就会想到,用过滤器或者基于项目框架的拦截器来做,但是顺着这个思路下 ...
- maven中pom的结构介绍
1.自己的坐标 groupId-->artifactId-->version> ` 2.打包方式 jar war pom packaging-->jar/war/pom 3. ...
- .NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
2.4.6 EF Core -- 更新 状态 自动变更检测 不查询删除和更新 并发 状态 Entity State Property State Entity State Added 添加 Uncha ...
- Docker 网络及命令
Docker常用命令 docker version #查看版本 docker search centos #搜索可用docker镜像 docker images 查看当前docker所有镜像 dock ...
- 四元数和旋转(Quaternion & rotation)
四元数和旋转(Quaternion & rotation) 本篇文章主要讲述3D空间中的旋转和四元数之间的关系.其中会涉及到矩阵.向量运算,旋转矩阵,四元数,旋转的四元数表示,四元数表示的旋转 ...
- 30天自制OS(linux环境)-day1
30天自制OS(linux环境)--第一天 我是在CentOS的环境上面实现的,使用ubuntu的环境也是类似的 第一步:因为要对二进制文件进行编辑,所以安装二进制编辑器hexedit(当然其他的也可 ...