You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{AsyncSeriesHook}from'tapable';classFrontEnd{constructor(){this.hooks={bundler: newAsyncSeriesHook(['bundler']),};}learnBundler(bundler){this.hooks.bundler.callAsync(bundler,()=>{console.timeEnd('costTime');});}}constXiaobai=newFrontEnd();Xiaobai.hooks.bundler.tapAsync('learn bundler1',(bundler,callback)=>{console.log(`Xiaobai learn ${bundler} for the first time`);setTimeout(()=>{callback();},1000);});Xiaobai.hooks.bundler.tapAsync('learn bundler2',(bundler,callback)=>{console.log(`Xiaobai learn ${bundler} for the second time`);setTimeout(()=>{callback();},2000);});console.time('costTime');Xiaobai.learnBundler('webpack');// Xiaobai learn webpack for the first time// 1s后 -> Xiaobai learn webpack for the second time// 2s后 -> costTime: 3010.48583984375ms
import{AsyncParallelHook}from'tapable';classFrontEnd{constructor(){this.hooks={bundler: newAsyncParallelHook(['bundler']),};}learnBundler(bundler){this.hooks.bundler.callAsync(bundler,()=>{console.timeEnd('costTime');});}}constXiaobai=newFrontEnd();Xiaobai.hooks.bundler.tapAsync('learn bundler1',(bundler,callback)=>{console.log(`Xiaobai learn ${bundler} for the first time`);setTimeout(()=>{callback();},2000);});Xiaobai.hooks.bundler.tapAsync('learn bundler2',(bundler,callback)=>{console.log(`Xiaobai learn ${bundler} for the second time`);setTimeout(()=>{callback();},1000);});console.time('costTime');Xiaobai.learnBundler('webpack');// Xiaobai learn webpack for the first time// Xiaobai learn webpack for the second time// 所有插件中最长的延时时间后 -> costTime: 2005.30908203125ms
import{SyncWaterfallHook}from'tapable';classFrontEnd{constructor(){this.hooks={framework: newSyncWaterfallHook(['framework']),};}learnFramework(framework){this.hooks.framework.call(framework);}}constXiaobai=newFrontEnd();// 上一个插件的返回值会当做下一个插件的入参Xiaobai.hooks.framework.tap('learn framework',(framework)=>{console.log(`${framework} is easy, let's play vue2`);return'vue2';});Xiaobai.hooks.framework.tap('learn framework',(arg)=>{console.log(`${arg} is also easy, let's play react`);return'react'});Xiaobai.hooks.framework.tap('learn framework',(arg)=>{console.log(`${arg} is amazing`);});Xiaobai.learnFramework('vue1');
③ Bail(熔断)
import{SyncBailHook}from'tapable';classFrontEnd{constructor(){this.hooks={framework: newSyncBailHook(),};}learnFramework(){this.hooks.framework.call();}}constXiaobai=newFrontEnd();// 只要其中一个插件有非undefined返回(null也算非undefined) 剩余插件全部停止执行Xiaobai.hooks.framework.tap('learn framework',()=>{console.log('vue is easy');returnundefined;});Xiaobai.hooks.framework.tap('learn framework',()=>{console.log('react is easy');returnnull;});// 上面return null, 'Angular is easy'不会被打印Xiaobai.hooks.framework.tap('learn framework',()=>{console.log('Angular is easy');returntrue;});Xiaobai.learnFramework();
GitHub - webpack/tapable: Just a little module for plugins.
Tapable总览
Tap 的英文单词解释,除了最常用的 点击 手势之外,还有一个意思是 水龙头 —— 在 webpack 中指的是后一种
Webpack 可以认为是一种基于事件流的编程范例,内部的工作流程都是基于 插件 机制串接起来,整个骨架基于Tapable,Tapable 是 Eventemitter 的升级版本,包含了 同步/异步 发布订阅模型, 在它的异步模型里又分为 串行/并行
基础使用
GitHub - webpack/tapable: Just a little module for plugins.
1、同步与异步
① 同步钩子
tap/call
② 异步钩子
tapAsync/callAsync + tapPromise/promise
2、串行与并行(Series/Parallel)
① 串行 Series
bundler
钩子是AsyncSeriesHook
的实例,这是一个异步串行钩子对
bundler
钩子注册了两个回调(在webpack中理解为注册了两个插件),只有当两个插件串行执行完了才会回到callAsync
的callback中,计算最后的时间,差不多是两个插件的延时时长相加(1s+2s -> 3s)② 并行 Parallel
把上面代码中的
AsyncSeriesHook
换成AsyncParallelHook
,其他不变bundler
钩子是AsyncParallelHook
的实例,这是一个异步并行钩子对
bundler
钩子注册了两个回调(在webpack中理解为注册了两个插件),只有当两个插件并行执行完了才会回到callAsync
的callback中,计算最后的时间,差不多是两个插件的耗时最长的那个3、钩子类型(Basic/Waterfall/Bail)
① Basic(基础类型)
这个没什么好说的,啥特异功能都没
② Waterfall(瀑布流)
③ Bail(熔断)
④ Loop(TODO)
官方都还没实现,不折腾了
看完上面几个例子,剩下的就是组合,详细同学们都能够举一反一,触类旁通,基础用法就不再一一演示了,可以自行动手尝试一下
实现SyncHook
下面我们来简单实现一个SyncHook
本质上是一个简单的发布订阅,Tap用来收集方法,call执行所有方法
SyncBailHook, SyncWaterfallHook, SyncLoopHook, AsyncParallelHook, AsyncParallelBailHook, AsyncSeriesHook, AsyncSeriesBailHook, AsyncSeriesWaterfallHook
等等都是基于上面的基础实现,加上同步、异步、并行、串行等变化,应用于不同的场景,有同学已经把所有类型都实现了一遍,此处不再写一遍,但还是建议参考着亲手实现一遍,加深理解脑壳疼的Webpack-tapable - 掘金
Tapable主要应用在Webpack的各个生命周期中,对它有个基础的了解后,才能比较容易理解webpack的插件应用,但也正是因为Tapable的灵活机制,webpack的源码读起来会比较跳,需要一定耐心和不断梳理总结才能慢慢掌握
The text was updated successfully, but these errors were encountered: