博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
webpack4.0各个击破(8)—— tapable篇
阅读量:5891 次
发布时间:2019-06-19

本文共 2252 字,大约阅读时间需要 7 分钟。

webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高。本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习webpack工具中相应的处理办法。(本篇中的参数配置及使用方式均基于webpack4.0版本

img_60140e31006b5776c5560aeedc0c6988.png

img_d6e7802c9640264835a13b85429f5a6a.png

一. tapable概述

tapable地址:

tapablewebpack的核心框架(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来注册事件监听。

img_d2b9870ae6953a047da2fd5328a048c6.png

这段代码并不复杂,调用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( )

img_58bf1964644b55f68261e351890d855b.png

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

  • Tapable.prototype.applyPluginsWaterfall( )

img_8a8bc0dece9f5ddbfcdb2b4aafe7eb17.png

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

  • Tapable.prototype.applyPluginsBailResult( )

img_d8556872a16a8f2dd1a5171c4b212348.png

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

  • Tapable.prototype.applyPluginsAsync( )

img_64539c14d7997428d246f463f5fa9fef.png

异步执行监听回调的方法。这个方法是顺序执行,等到第一个插件执行结束后才会执行下一个插件,实现的方式就是将下一个插件当做回调函数传入第一个插件,在第一个插件的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版本做了很大改进,使用ES6语法重写了整个框架,除了更换了API外,在插件定义方面进行了明显升级,原来只通过plugin( )方法来定义插件,不阅读源码很难知道插件的规范格式,新版本的tapable提供了基本样例,细分的事件钩子(*Hook),新的触发事件的方法(tap,tapAsync,tapPromise)等等,但实现的基本需求是一致的,感兴趣的读者可以自行学习。

转载地址:http://lgfsx.baihongyu.com/

你可能感兴趣的文章
[LeetCode] Meeting Rooms II
查看>>
从Swift学习iOS开发的路线指引
查看>>
汉诺塔问题探讨
查看>>
chattr和lsattr命令详解
查看>>
3.1链表----链表(Linked List)入门
查看>>
[布局] bootstrap基本标签总结
查看>>
异步编程思想
查看>>
"数学口袋精灵"bug(团队)
查看>>
2017python第六天作业 面向对象 本节作业: 选课系统
查看>>
vue实现单页应用demo
查看>>
【找规律】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) B. Code For 1...
查看>>
【最短路】【spfa】CDOJ1633 去年春恨却来时,落花人独立,微雨燕双飞
查看>>
Scribes:小型文本编辑器,支持远程编辑
查看>>
HDU 1065 - I Think I Need a Houseboat
查看>>
为什么要使用 SPL中的 SplQueue实现队列
查看>>
文件的相关操作(创建、打开、写入、读出、重命名)
查看>>
Redis与memecache的区别
查看>>
jQuery分步步骤
查看>>
品尝阿里云容器服务:用nginx镜像创建容器,体验基于域名的路由机制
查看>>
PHP const关键字
查看>>