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模块是必须的。一部分逻辑绑定事件,一部分逻辑触发事件,本质是还是发布订阅逻辑。


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


分享到:


相關文章: