一.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) 串行和我们的同步钩子是很接近的,只不过多了一步回调操作
/**************************************************************************************************************************************************************************/
“如约而至”是个多么美好的词,等的辛苦,却从不辜负。

webpack4.X核心工具库之tapable实例对象Hook的更多相关文章

  1. webpack4.0各个击破(8)—— tapable篇

    webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...

  2. 25个Java机器学习工具&库--转载

    本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...

  3. java25个Java机器学习工具&库

    本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...

  4. Java第三方工具库/包汇总

    一.科学计算或矩阵运算库 科学计算包: JMathLib是一个用于计算复杂数学表达式并能够图形化显示计算结果的Java开源类库.它是Matlab.Octave.FreeMat.Scilab的一个克隆, ...

  5. Python——详解collections工具库

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天为大家介绍Python当中一个很好用也是很基础的工具库,叫做collections. collection在英文当中有容器的意思,所以顾 ...

  6. 学以致用:手把手教你撸一个工具库并打包发布,顺便解决JS浮点数计算精度问题

    本文讲解的是怎么实现一个工具库并打包发布到npm给大家使用.本文实现的工具是一个分数计算器,大家考虑如下情况: \[ \sqrt{(((\frac{1}{3}+3.5)*\frac{2}{9}-\fr ...

  7. Webpack4.0各个击破(8)tapable篇

    目录 一. tapable概述 二. tapable-0.2源码解析 2.1 代码结构 2.2 事件监听方法 2.3 事件触发方法 三. tapable1.0概述 一. tapable概述 tapab ...

  8. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

  9. JSP 核心标签库

    1 JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 2 JSTL标签库分类 核心标 ...

随机推荐

  1. Spark调优 | Spark Streaming 调优

    Spark调优 | Spark Streaming 调优 1.数据序列化 2.广播大变量 3.数据处理和接收时的并行度 4.设置合理的批处理间隔 5.内存优化 5.1 内存管理 5.2优化策略 5.3 ...

  2. 利用powershell隐藏执行后门

    运行后门时,有些后门不能中断.双击运行这种后门会产生一个黑框. 一条命令就能使其在后台执行 命令解释: start-process启动一个进程 -windowstyle窗口样式 hidden隐藏

  3. Pytest(17)运行未提交的git(pytest-picked)

    前言 我们每天写完自动化用例后都会提交到 git 仓库,随着用例的增多,为了保证仓库代码的干净,当有用例新增的时候,我们希望只运行新增的未提交 git 仓库的用例.pytest-picked 插件可以 ...

  4. F - Courses (学生选课(匈牙利算法模板))

    题目大意:一共有N个学生跟P门课程,一个学生可以任意选一门或多门课,问是否达成: 1.每个学生选的都是不同的课(即不能有两个学生选同一门课) 2.每门课都有一个代表(即P门课都被成功选过) 输入为: ...

  5. LA 3641 Leonardo的笔记本 & UVA 11077 排列统计

    LA 3641 Leonardo的笔记本 题目 给出26个大写字母的置换B,问是否存在要给置换A,使得 \(A^2 = B\) 分析 将A分解为几个循环,可以观察经过乘积运算得到\(A^2\)后,循环 ...

  6. c语言实现--双向循环链表操作

    1,双向链表相当于两个单向循环链表. 2,双向链表的结点定义. 1 struct DULNode 2 { 3 int data; 4 struct DULNode * prior; 5 struct ...

  7. Codeforces Round #272 (Div. 2) B. Dreamoon and WiFi (暴力二进制枚举)

    题意:给你一个只含\(+\)和\(-\)的字符串,统计它的加减和,然后再给你一个包含\(+,-,?\)的字符串,其中\(?\)可以表示为\(+\)或\(-\),问有多少种情况使得第二个字符串的加减和等 ...

  8. ucosIII学习笔记——钩子函数

    一开始听见钩子函数感觉很莫名其妙,更不知道它有何作用,这是第一篇博客,也是学习ucosIII操作系统的一个开始吧. 在系统中有开发者自己创建的任务也有系统内部任务 ,UCOSIII中有五个系统任务,分 ...

  9. Rsyncd 同步服务

    目录 数据备份的策略 三种数据备份 三种数据备份的比较(转载) 不同数据备份类型组合说明(转载) Rsyncd 服务传输模式(remote synchronizetion deamon) 本地传输模式 ...

  10. 秋招C++面试相关总结索引

    C++相关 C++ part1 C++ part2 C++ part3 C++ part4 C++ part5 C++ part6 C++ part6.5 C++ part7 C++ part8 C+ ...