显微镜下的webpack4:灵魂tapable,终于搞懂钩子系列!

 

简介

大家在看webpack源码的时候,有没有感觉像再看天书,似乎没有办法一个文件比如webpack.js从头看到尾。感觉webpack的跳跃性很强,完全不知道程序在运行的时候,发生了什么。完全不清楚这个事件是什么时候发生的,比如loader是什么时候执行的,plugin又是什么时候出现的。webpack的程序错综复杂,完全迷失在程序之中。这究竟是为什么呢?其实很简单!因为webpack的灵魂Tapable!这个机制使得webpack异常的灵活,它有一句经典的话——Everything is a plugin!。由此可见webpack是靠插件堆积起来的。而实现这个插件机制的就是Tabable!

Events

webpack的灵魂Tapable,有点类似于nodejs的Events,都是注册一个事件,然后到了适当的时候触发。这里的事件触发是这样绑定触发的,通过on方法,绑定一个事件,emit方法出发一个事件。Tapable的机制和这类似,也是tap注册一个事件,然后call执行这个事件。

const EventEmitter = require('events'); const myEmitter = new EventEmitter(); //on的第一个参数是事件名,之后emit可以通过这个事件名,从而触发这个方法。 //on的第二个参数是回掉函数,也就是此事件的执行方法 myEmitter.on('newListener', (param1,param2) => {     console.log("newListener",param1,param2) }); //emit的第一个参数是触发的事件名 //emit的第二个以后的参数是回调函数的参数。 myEmitter.emit('newListener',111,222);

Tapable究竟为何物

如果我们把Tapable的实例对象比作一颗参天大树,那么的每一根树枝就是一个挂载的hook(钩子),也就是Tapable之中给每一个事件分门别类的机制,比如编译(compile.js)这个对象中,又运行(run)的钩子,有构建(make)的钩子,这些钩子就像树枝一样,组成了一棵树的骨干,然后每个树枝上的树叶就是每个钩子上面挂载的函数方法。树枝(钩子)越多,树叶(函数)越多,此树越茂密(程序越复杂)。

当然这只是一个简易的理解。实际上,webpack中不止有一棵树,每棵树之间还有错综复杂的关系。比如有些方法如compilation.js中的一些方法,就要等compile.js中的make这个钩子执行之后才会执行。那么我们就从了解Tapable中钩子的用法,来理解webpack中tapable。

以工作日为例,了解Tapable的用法

即使webpack中的每颗tapable的树之间有错综复杂的关系,整个程序都有一个逻辑线,也就是游戏中的主线剧情,我们先构建我们工作日的主线剧情。

主线剧情

让我们来回一下,我们的日常工作日,应该大多数分成3个阶段,上班前,上班中和下班后,这3个时间段。这三个时间段,我用了3中钩子类型,普通型,流水型和熔断型。
按照文档他们的解释是这样的:

  • 普通型basic:这个比较好理解就是按照tap的注册顺序一个个向下执行。
  • 流水型water:这个相对于basic的区别就是,虽然也是按照tap的顺序一个个向下执行,但是如果上一个tap有返回值,那么下一个tap的传入参数就是上一个tap的返回值。
  • 熔断型bail:这个相对于water的区别就是,如果返回了null以外的值,就不继续执行了。

是不是感觉一个事件的订阅发布怎么可以分出这么多类型?不要急,每个类型都有他的作用!

钩子的语法一般都是new 钩子类型Hook([参数名1,参数名2,参数名3]),这里的数组是只是提示你传入参数有几个,给了名字只是为了可读性,如果你想写一个别人看不懂的可以这样new SyncHook(["a","b","c"]),这里要注意这个参数名的类型是字符串。如果没有提前准备号需要传入的参数,后续挂函数的时候,就无法传入参数了。这个设计应该是为了日后好打理,告诉其他开发者,我传入的参数类型。

class MyDaily {     constructor() {         this.hooks = {             beforeWork: new SyncHook(["getUp"]),             atWork: new SyncWaterfallHook(["workTask"]),             afterWork: new SyncBailHook(["activity"])         };     }     tapTap(){         //此处是行为     }     run(){         this.hooks.beforeWork.call()         this.hooks.atWork.call()         this.hooks.afterWork.call()     } }

一天我们不可能什么事都不做,所以给钩子上加点事,

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信