02.29 webpack的钩子是如何实现的?弄懂tapable模块你就知道了

这篇文章给大家介绍一个模块——tapable,它可以专门用来创建钩子,例如webpack中的钩子就是用它来创建的。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图1

如图1所示,tapable提供了很多的构造函数,我们利用这些构造函数就可以创建钩子。

SyncHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图2

如图2,所有hook构造函数的使用都是先new一个对象,参数是一个数组,这个数组的每个元素和下面tap方法的回调函数的参数是一一对应的。换句话说,这个数组有几个元素,tap方法的回调函数就有几个参数。

call方法的参数和tap方法回调函数的参数也是一一对应的,在运行时,图2中的1、2、3参数将会依次传入arg1、arg2、arg3中。

咱们运行一下,如下:

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图3

从运行结果看,我们所言不虚,其他的hook的参数传递也是如此。

tap方法绑定回调,call方法触发,h1先执行,h2后执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图4

tap方法绑定回调,promise方法触发,h1先执行,h2后执行。但是hook.promise方法会返回一个promise对象,如果h1、h2执行中有异常,可以在后面直接catch。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图5

tap方法绑定回调,callAsync方法触发,h1先执行,h2后执行。但是hook.callAsync方法需要多传入一个回调函数,如果h1、h2执行中有异常,就会把错误传递给callAsync的回调函数,如果没有异常,h1和h2完成执行后就会执行callAsync的回调函数。

SyncBailHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图6

tap方法绑定回调,call方法触发,h1先执行,h2后执行。如果h1返回非undefined的值,那么h2就不会执行,如果h1返回undefined,那么h2就会执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图7

tap方法绑定回调,promise方法触发,h1先执行,h2后执行。如果h1返回非undefined的值,那么h2就不会执行,h1的值通过promise对象传递出来,如果h1返回undefined,那么h2就会执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图8

tap方法绑定回调,callAsync方法触发,如果h1返回结果,就会直接执行callAsync的回调,如果没有再去执行h2,如果h2也没有返回结果,最后callAsync的回调方法也会被执行。

SyncWaterfallHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图9

tap方法绑定回调,call方法触发,h1先执行,h1的返回结果会当做h2的第一个参数,h2再执行,h2的返回结果会当做h3的第一个参数,h3再执行,h3没有返回结果,依然把h2的返回结果传给h4的第一个参数,h4再执行,以此类推。。。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图10

tap方法绑定回调,promise方法触发,h1先执行,h1的返回结果会当做h2的第一个参数,h2再执行,h2的返回结果会当做h3的第一个参数,h3再执行,h3没有返回结果,依然把h2的返回结果传给h4的第一个参数,h4再执行,以此类推,最后通过promise对象返回。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图11

tap方法绑定回调,callAsync方法触发,执行逻辑和图9图10一致,最后通过callAsync的回调函数返回结果。

SyncLoopHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图12

tap方法绑定回调,call方法触发,如果h1返回结果,会再次执行h1,直到h1不返回任何值,然后再去执行h2,如果h2返回结果,会回到h1从头开始执行,只有h1、h2都不返回值才会执行h3,如果h3有返回值又会回头从h1开始执行,只有所有回调都没有返回值,整个执行程序才会结束。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图13

tap方法绑定回调,promise方法触发,执行逻辑同上。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图14

tap方法绑定回调,callAsync方法触发,执行逻辑同上。

AsyncParallelHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图15

tap方法绑定回调,promise方法触发,h1、h2、h3会依次执行,最终会返回一个promise对象。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图16

tap方法绑定回调,callAsync方法触发,h1、h2、h3会依次执行,最后会执行callAsync的回调函数。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图17

tapPromise方法绑定回调,promise方法触发,每个tapPromise回调函数必须返回一个promise对象,这些promise对象的执行是平行的,只有当这些promise都执行完成才会执行hook.promise的回调函数。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图18

tapPromise方法绑定回调,callAsync方法触发,执行逻辑同图17。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图19

tapAsync方法绑定回调,promise方法触发,tapAsync回调函数的最后一个参数都会传入一个callback,只有每个callback都执行完成,hook.promise返回的promise对象才会执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图20

tapAsync方法绑定回调,callAsync方法触发,执行逻辑同上。

AsyncParallelBailHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图21

tap方法绑定回调,promise方法触发,h1如果有结果返回,h2、h3都不会执行,h1没有结果返回,才会执行h2,h2有结果返回,h3就不会执行,以此类推。。。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图22

tap方法绑定回调,callAsync方法触发,执行逻辑同图21。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图23

tapPromise方法绑定回调,promise方法触发,无论h1何时返回,只要h1有值,那么最终的结果就是h1的值,如果h1没有值,那么看h2有没有值,以此类推。。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图24

tapPromise方法绑定回调,callAsync方法触发,逻辑同图23。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图25

tapAsync方法绑定回调,promise方法触发,cb全部执行,hook.promise返回的promise对象才会执行,返回的结果是tapAsync回调的第一个有值的结果。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图26

tapAsync方法绑定回调,callAsync方法触发,逻辑同图25。

AsyncSeriesHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图27

tap方法绑定回调,promise方法触发,h1、h2、h3会顺序执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图28

tap方法绑定回调,callAsync方法触发,h1、h2、h3会顺序执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图29

tapPromise方法绑定回调,promise方法触发,h1先执行,h2再执行,最后h3才执行,顺序执行。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图30

tapPromise方法绑定回调,callAsync方法触发,逻辑同图29。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图31

tapAsync方法绑定回调,promise方法触发,逻辑同图29。

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图32

tapAsync方法绑定回调,callAsync方法触发,逻辑同图29。

AsyncSeriesBailHook

webpack的钩子是如何实现的?弄懂tapable模块你就知道了

图33

tap方法绑定回调,promise方法触发,h1先执行,如果h1有返回结果,h2、h3就不会再执行,h1无返回结果,才会继续执行h2、h3,以此类推。。。

其他的情况作者就不写了,我相信聪明的你肯定找到了规律。还剩一个hook构造函数AsyncSeriesWaterfallHook,小伙伴们可以自己尝试写写看看有什么样的执行逻辑。

总结

如果你想要了解webpack,或者想开发一个webpack的插件,搞清楚tapable模块是必须的。一部分逻辑绑定事件,一部分逻辑触发事件,本质是还是发布订阅逻辑。


喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!


分享到:


相關文章: