热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

webpack4.X核心工具库之tapable实例对象Hook

一.tapable简介tapable为webpack底层的核心工具库,webpack许多功能的实现都是跟它密不可分的,webpack的编译流程为配置初始化---内容编译---输

一.tapable简介

tapable为webpack底层的核心工具库,webpack许多功能的实现都是跟它密不可分的,webpack的编译流程为配置初始化--->内容编译--->输出编译后内容,这三个的整体执行过程可以称之为

事件驱动型事件流工作机制,这个机制将不同的工作流串联起来完成所有的工作,其中最为核心的两个部分是 负责编译的complier 负责创建bundles的compilation。tapable本身是一个独立的库

在webpack中进行了大量的使用,tapable工作流程是 实例化hook注册事件监听---->通过hook触发事件监听---->执行懒编译生成的可执行代码。

二.Hook简介

Hook本质是tapable实例对象,hook执行机制可分为同步和异步,对于异步来说又存在着并行和串行两种,其中hook的执行特点如下:

Hook:普通钩子,监听器之间互相独立不干扰。

BailHook:熔断钩子,某个监听返回非undefined时后续不执行。

WaterfallHook:瀑布沟子,上一个监听返回值可传递至下一个。

LoopHook:循环钩子,如果当前未返回false则一直执行。

tapable库同步钩子分为SynckHook,SyncBailHook,SyncWaterfallHook,SyncLoopHook。

tapable库异步串行钩子分为AsyncSeriesHook,AsyncSeresBailHook,AsynvSeriesWaterfallHook。

tapable库异步并行钩子分为AsyncParalleHook,AsyncParalleBailHook。

三.同步钩子的使用

1.同步钩子之syncHook

const { SyncHook } =require('tapable')
//钩子实例
let hook =new SyncHook(['name','age'])
hook.tap(
'fn1',function(name,age){
console.log(
'fn1---->',name,age)
})
hook.tap(
'fn2',function(name,age){
console.log(
'fn2---->',name,age)
return 'res'
})
hook.tap(
'fn3',function(name,age){
console.log(
'fn3---->',name,age)
})
//触发监听
hook.call('lw','18')
//打印结果为 fn1-----> lw 18 fn2-----> lw 18 fn3-----> lw 18

上述代码中即便fn2 return了后面的fn3依然会执行。

2.同步钩子之syncBialHook

const { SyncBailHook } =require('tapable')
//钩子实例
let hook =new SyncBailHook(['name','age'])
hook.tap(
'fn1',function(name,age){
console.log(
'fn1---->',name,age)
})
hook.tap(
'fn2',function(name,age){
console.log(
'fn2---->',name,age)
return 'res'
})
hook.tap(
'fn3',function(name,age){
console.log(
'fn3---->',name,age)
})
//触发监听
hook.call('lw','100')
//打印结果为 fn1-----> lw 18 fn2-----> lw 18

上述代码中与SyncHook不同的是fn2中添加一个return (非undefined) 后面的fn3不会执行,说明这条流水线断掉了

3.同步钩子之syncWaterfallHooks

const { SyncWaterfallHook } =require('tapable')
//钩子实例
let hook =new SyncWaterfallHook(['name','age'])
hook.tap(
'fn1',function(name,age){
console.log(
'fn1---->',name,age)
return 'ret1'
})
hook.tap(
'fn2',function(name,age){
console.log(
'fn2---->',name,age)
return 'ret2'
})
hook.tap(
'fn3',function(name,age){
console.log(
'fn3---->',name,age)
return 'ret3'
})
//触发监听
hook.call('lw','100')
//打印结果为 fn1-----> lw 18 fn2-----> ret1 18 fn3-----> ret2 18

这个钩子的特点是通过上一个监听返回的ret1传给下一个钩子函数fn2 然后返回 依次类推 所以又叫瀑布沟子

4.同步钩子之SyncLoopHook

const { SyncLoopHook } =require('tapable')
//钩子实例
let hook =new SyncLoopHook(['name','age'])
let count1
=0
let count2
=0
let count3
=0
hook.tap(
'fn1',function(name,age){
console.log(
'fn1---->',name,age)
if(++count1==1){
count1
=0
return undefined
}
return true;
})
hook.tap(
'fn2',function(name,age){
console.log(
'fn2---->',name,age)
if(++count2==2){
count2
=0
return undefined
}
return true
})
hook.tap(
'fn3',function(name,age){
console.log(
'fn3---->',name,age)
})
//触发监听
hook.call('lw','100')
//打印结果为:fn1-----> lw 18 fn2-----> lw 18 fn1-----> lw 18
//fn2-----> lw 18 fn3-----> lw 18

从打印结果可以看出循环执行了2遍,第一次执行到了fn2停止,第二次3个函数执行完经调试代码得知底层是一个
do while循环,while的重新执行条件为return内容为true。
四.异步钩子的使用
对于异步钩子的使用,在添加事件监听时会存在三种方式:tap tapAsync tapPromise。

1.tapable库异步并行钩子

//第一种方式 tap
const { AsyncParallelHook } =require('tapable')
//钩子实例
let hook =new AsyncParallelHook(['name'])
hook.tap(
'fn1',function(name){
console.log(
'fn1---->',name)
})
hook.tap(
'fn2',function(name){
console.log(
'fn2---->',name)
})
hook.callAsync(
'lw',function(){
console.log(
'回调操作最后执行')
})
//打印结果 fn1---->lw fn2----->lw 最后执行回调

并行钩子的tap方法是同步进行的,只是从打印结果的话很难看出同步进行,下面通过另一种方式

改动下看下效果。

//第二种方式 tapAsync
//通过settimeOut异步操作,如果为并行执行的话,执行结果应该偏向于大的时间数值,
//我们用console.time标记下,代码如下:

const { AsyncParallelHook } =require('tapable')
//钩子实例
let hook =new AsyncParallelHook(['name'])
console.time(
'time')
hook.tapAsync(
'fn1',function(name,callback){
setTimeout(()
=>{
console.log(
'fn1---->',name)
callback()
},
1000)
})

hook.tapAsync(
'fn2',function(name,callback){
setTimeout(()
=>{
console.log(
'fn2---->',name)
callback()
},
2000)
})

hook.callAsync(
'lw',function(){
console.log(
'回调操作最后执行')
console.timeEnd(
'time')
})
//打印结果为fn1--->lw fn2--->lw
//同步打印出来 time:2.002s 所以证明是并行执行

//第三种方式 tapPromise
const { AsyncParallelHook } =require('tapable')
//钩子实例
let hook =new AsyncParallelHook(['name'])
console.time(
'time')
hook.tapPromise(
'fn1',function(name){
return new Promise(function(resolve,reject){
setTimeout(()
=>{
console.log(
'fn1---->',name)
resolve()
},
1000)
})
})

hook.tapPromise(
'fn2',function(name){
return new Promise(function(resolve,reject){
setTimeout(()
=>{
console.log(
'fn2---->',name)
resolve()
},
2000)
})
})

hook.promise(
'lw').then(()=>{
console.log(
'end执行了')
console.timeEnd(
'time')
})
//打印结果为fn1--->lw fn2--->lw
//同步打印出来 time:2.002s 同样并行执行

//AsyncParallelBailHook
const { AsyncParallelBailHook } =require('tapable')
//钩子实例
let hook =new AsyncParallelBailHook(['name'])
console.time(
'time')
hook.tapAsync(
'fn1',function(name,callback){
setTimeout(()
=>{
console.log(
'fn1---->',name)
callback()
},
1000)
})
hook.tapAsync(
'fn2',function(name,callback){
setTimeout(()
=>{
console.log(
'fn2---->',name)
callback(
'err')
},
2000)
})
hook.tapAsync(
'fn3',function(name,callback){
setTimeout(()
=>{
console.log(
'fn3---->',name)
callback()
},
3000)
})

hook.callAsync(
'lw',function(){
console.log(
'最后的回调执行了')
console.timeEnd(
'time')
})
//打印结果为fn1---->lw fn2--->lw
//最后函数回调执行了 time:2.002s fn3--->lw

从打印结果来看fn2里面callback('err') 返回错误 所以在fn2进行时阻断掉了,总运行时长接近2s
最后fn3也打印出来是因为终归有个settimeout控制着所以到达3s会被打印。
2.tapable库异步串行钩子

const { AsyncSeriesHook } =require('tapable')
//钩子实例
let hook =new AsyncSeriesHook(['name'])
console.time(
'time')
hook.tapPromise(
'fn1',function(name){
return new Promise(function(resolve,reject){
setTimeout(()
=>{
console.log(
'fn1---->',name)
resolve()
},
1000)
})
})

hook.tapPromise(
'fn2',function(name){
return new Promise(function(resolve,reject){
setTimeout(()
=>{
console.log(
'fn2---->',name)
resolve()
},
2000)
})
})

hook.promise(
'lw').then(()=>{
console.log(
'end执行了')
console.timeEnd(
'time')
})
//打印结果为fn1--->lw fn2--->lw time:3.002s(1s+2s)
//串行和我们的同步钩子是很接近的,只不过多了一步回调操作

/*****************************************************/
“如约而至”是个多么美好的词,等的辛苦,却从不辜负。

---感谢阅读,o(* ̄︶ ̄*)o开心每一天!



推荐阅读
author-avatar
李波2602884584
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有