由浅入深学习Tapable
文章目录
- 由浅入深学习Tapable
- Tapable是什么
- Tapable的Hook分类
- 同步和异步的
- 使用
- Sync*同步类型钩子
- 基本使用
- bail
- Loop
- Waterfall
- Async*异步类型钩子
- Parallel
- Series
由浅入深学习Tapable
webpack有两个非常重要的类:Compiler和Compilation。他们通过注入插件的方式,来监听webpack的所有生命周期,插件的注入离不开各种各样的Hook,而他们的Hook是如何得到的呢?其实是创建了Tapable库中各种Hook的实例。
Tapable是什么
Tapable是一个任务调度库,它的核心思基于发布订阅模式是将任务执行逻辑和调度逻辑分离,Tapable在webpack中用于plugin的管理,在可以实现复杂调度逻辑的同时尽可能保证可维护性。
Tapable的机制与Event类似,它可以用来定义各种各样的钩子,相当于Event中的事件注册,但是与Event不同的是,Event中各个事件之间相互不关联,互不影响,但是tapable注册的事件之间可以是有关系的,这种关系通过Tapable定义的各个钩子类来实现。其实,Tapable的核心就是这些钩子类。因此,我们接下来的重点就是讲述这些钩子类,并实现它们。
Tapable的Hook分类
同步和异步的
- 以sync开头的,是同步的Hook
- 以async开头的,两个事件处理回调,不会等待上一次处理回调结束后再执行下一次回调

使用
Tapable的每个子类都是一个用于注册和触发事件的钩子,我们可以查看一下SyncHook实例身上有哪些属性,找到它注册事件和触发事件的属性。
SyncHook {_args: [],name: undefined,taps: [],interceptors: [],_call: [Function: CALL_DELEGATE],call: [Function: CALL_DELEGATE], // 用于触发同步事件的钩子_callAsync: [Function: CALL_ASYNC_DELEGATE],callAsync: [Function: CALL_ASYNC_DELEGATE], // 用于触发异步事件的钩子_promise: [Function: PROMISE_DELEGATE],promise: [Function: PROMISE_DELEGATE],_x: undefined,compile: [Function: COMPILE],tap: [Function: tap], // 用于注册同步事件的钩子tapAsync: [Function: TAP_ASYNC], // 用于注册异步事件的钩子tapPromise: [Function: TAP_PROMISE],constructor: [Function: SyncHook]
}
Sync*同步类型钩子
基本使用
const { SyncHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 创建hooks(webpack完成)syncHook: new SyncHook(["name", "age"]),};// 2. 用hooks监听事件(自定义plugin)this.hooks.syncHook.tap("event1", (name, age) => {console.log("event1事件监听执行了:", name, age);});this.hooks.syncHook.tap("event2", (name, age) => {console.log("event2事件监听执行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 发出去事件(webpack完成)
compiler.hooks.syncHook.call("小张", 20);
结果:

bail
当有返回值时,就不会执行后续的事件触发了
const { SyncBailHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 创建hooksbailHook: new SyncBailHook(["name", "age"]),};// 2. 用hooks监听事件(自定义plugin)this.hooks.bailHook.tap("event1", (name, age) => {console.log("event1事件监听执行了:", name, age);return 123});this.hooks.bailHook.tap("event2", (name, age) => {console.log("event2事件监听执行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 发出去事件
compiler.hooks.bailHook.call("小张", 20);
输出结果:

Loop
当返回值为true,就会反复执行该事件,当返回值为undefined或者不返回内容,就退出事件
const { SyncLoopHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 创建hooksloopHook: new SyncLoopHook(["name", "age"]),};let count = 0;// 2. 用hooks监听事件(自定义plugin)this.hooks.loopHook.tap("event1", (name, age) => {if (count < 5) {console.log("event1事件监听执行了:", name, age);count++;return true;} else {return;}});this.hooks.loopHook.tap("event2", (name, age) => {console.log("event2事件监听执行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 发出去事件
compiler.hooks.loopHook.call("小张", 20);
输出结果:

Waterfall
当返回值不为undefined时,会将这次返回的结果作为下次事件的第一个参数
const { SyncWaterfallHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 创建hookswaterfallHook: new SyncWaterfallHook(["name", "age"]),};// 2. 用hooks监听事件(自定义plugin)this.hooks.waterfallHook.tap("event1", (name, age) => {console.log("event1事件监听执行了:", name, age);// return “小李”,小李作为下一个事件的第一个参数return "小李";});this.hooks.waterfallHook.tap("event2", (name, age) => {console.log("event2事件监听执行了:", name, age);});}
}const compiler = new myCompiler();
// 3. 发出去事件
compiler.hooks.waterfallHook.call("小张", 20);
输出结果:

Async*异步类型钩子
Parallel
并行,不会等到上一个事件回调执行结束,才会执行下一次事件处理回调
const { AsyncParallelHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 创建hooksparallelHook: new AsyncParallelHook(["name", "age"]),};// 2. 用hooks监听事件(自定义plugin)this.hooks.parallelHook.tapAsync("event1", (name, age) => {setTimeout(() => {console.log("event1事件监听执行了:", name, age);}, 3000);});this.hooks.parallelHook.tapAsync("event2", (name, age) => {setTimeout(() => {console.log("event2事件监听执行了:", name, age);}, 3000);});}
}const compiler = new myCompiler();
// 3. 发出去事件
compiler.hooks.parallelHook.callAsync("小张", 20);
输出结果:

Series
串行,会等待上一次异步的Hook,即按照注册的顺序依次执行
const { AsyncSeriesHook } = require("tapable");class myCompiler {constructor() {this.hooks = {// 1. 创建hooksseriesHook: new AsyncSeriesHook(["name", "age"]),};// 2. 用hooks监听事件(自定义plugin)this.hooks.seriesHook.tapAsync("event1", (name, age, callback) => {console.log("event1事件监听执行了:", name, age);// 这个callback决定下一个事件的执行callback();});this.hooks.seriesHook.tapAsync("event2", (name, age, callback) => {console.log("event2事件监听执行了:", name, age);// 这个callback决定发出事件中的函数执行callback();});}
}const compiler = new myCompiler();
// 3. 发出去事件
// 第三个参数决定第一个事件的执行
compiler.hooks.seriesHook.callAsync("小张", 20, () => {console.log("所有事件都执行完成啦!");
});
输出结果:


相关文章:
由浅入深学习Tapable
文章目录 由浅入深学习TapableTapable是什么Tapable的Hook分类同步和异步的 使用Sync*同步类型钩子基本使用bailLoopWaterfall Async*异步类型钩子ParallelSeries 由浅入深学习Tapable webpack有两个非常重要的类:Compiler和Compilation。他们通过注入插件的方式&a…...
YOLOv5白皮书-第Y6周:模型改进
📌本周任务:模型改进📌 注:对yolov5l.yaml文件中的backbone模块和head模块进行改进。 任务结构图: YOLOv5s网络结构图: 原始模型代码: # YOLOv5 v6.0 backbone backbone:# [from, number, module, args]…...
word之插入尾注+快速回到刚才编辑的地方
1-插入尾注 在编辑文档时,经常需要对一段话插入一段描述或者附件链接等,使用脚注经常因占用篇幅较大导致文档页面内容杂乱,这事可以使用快捷键 ControlaltD 即可在 整个行文的末尾插入尾注,这样文章整体干净整洁,需…...
Qt扫盲-QTableView理论总结
QTableView理论总结 一、概述二、导航三、视觉外观四、坐标系统五、示例代码1. 性别代理2. 学生信息模型3. 对应视图 一、概述 QTableView实现了一个tableview 来显示model 中的元素。这个类用于提供之前由QTable类提供的标准表,但这个是使用Qt的model/view架构提供…...
从外部访问K8s中Pod的五种方式
hostNetwork、 hostPort、 NodePort、 LoadBalancer、 Ingress 暴露Pod与Service一样,因为Pod就是Service的backend 1、hostNetwork:true 这是一种直接定义 Pod 网络的方式。 如果在 Pod 中使用 hostNetwork:true 配置, pod 中运行的应用程序…...
什么是A股交易接口_(股票交易c接口)开发原理
A股交易接口是指用于与国内的证券交易所(上海证券交易所和深圳证券交易所)进行股票买卖交易的电子接口或软件系统。A股交易接口是金融机构、券商以及个人投资者的必备掌握操作技能之一,它提供了实时的股票行情、交易下单、撤单、查询账户信息…...
STM32F4X NVIC中断概念
STM32F4X NVIC中断概念 CPU查询状态两种方式轮询查询中断查询 STM32有关中断的概念中断向量表系统中断外设中断中断号中断优先级 STM32F4X NVIC控制器NVIC控制器简介NVIC寄存器优先级分组 STM32F4X中断配置优先级分组设置配置外设中断 CPU查询状态两种方式 在讲解中断的概念之…...
关于consul的下载方法
linux下 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo sudo yum -y install consulwindow下 https://developer.hashicorp.com/consul/downloads 然后把里面的exe文件放在gopath下就行了 验证…...
应用在汽车前照灯系统中的环境光传感芯片
为了保证行车照明的安全性和方便性,减轻驾驶员的劳动强度。近年来,出现了许多新的照明控制系统,例如用于日间驾驶的自动照明系统、光束调节系统、延迟控制等。尤其是汽车自适应前照灯系统,它是一种能够自动改变两种以上的光型以适…...
Python Flask+Echarts+sklearn+MySQL(评论情感分析、用户推荐、BI报表)项目分享
Python FlaskEchartssklearnMySQL(评论情感分析、用户推荐、BI报表)项目分享 项目背景: 随着互联网的快速发展和智能手机的普及,人们越来越倾向于在网上查找餐厅、购物中心、酒店和旅游景点等商户的点评和评分信息,以便做出更好的消费决策。…...
开源项目-高校自动排课系统
哈喽,大家好,今天给大家带来一个开源项目-基于遗传算法的一个高校自动排课系统,同时也是一个前后端分离项目。 前端:React 后端:SpringBoot+MyBatis+MySQL数据库 高校自动排课系统的主要功能包括查询模块,安排教学区域,排课页面三部分 登录 查询模块 可以根据学年…...
IP网络广播系统草坪音箱景区系统防水石头,草坪音箱的应用
IP网络广播系统草坪音箱景区系统防水石头,草坪音箱的应用 SV-7045V是深圳锐科达电子有限公司的一款防水网络草坪音箱,具有10/100M以太网接口,可将网络音源通过自带的功放和喇叭输出播放,可达到功率20W。常用场景:公园ip草坪音箱&…...
拒绝摆烂!C语言练习打卡第二天
🔥博客主页:小王又困了 📚系列专栏:每日一练 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、选择题 📝1.第一题 📝2.第二题 📝…...
第四章:前端框架Vue基础入门
文章目录 一、Vue框架概述1.1 声明响应式的数据 二、Vue内置指令2.1、条件渲染指令v-if/v-show2.2 v-for: 列表渲染2.3、v-text/v-html 模板指令2.4 v-on:事件监听器2.6 动态绑定v-bind2.7 v-model表单元素值绑定 三、计算属性与监视3.1 计算属性computed3.2 watch侦听器3.3 wa…...
企业权限管理(十三)-用户关联角色操作
用户关联角色操作 从前台发送请求 <a href"${pageContext.request.contextPath}/user/findUserByIdAndAllRole.do?id${user.id}" class"btn bg-olive btn-xs">添加角色</a>查询用户以及用户可以添加的角色 usercontroller //查询用户以及用…...
深入理解Vue 3.0x中的Suspense和异步组件
深入理解Vue 3.0x中的Suspense和异步组件 Vue 3.0x作为Vue.js框架的最新版本,引入了许多创新特性,其中Suspense和异步组件是重要的改进之一。在本文中,我们将深入探讨这两个特性,了解它们如何为现代Web应用带来更好的性能和用户体…...
Ajax 笔记(三)—— Ajax 原理
笔记目录 3. Ajax 原理3.1 XMLHttpRequest3.1.1 XHR 使用步骤3.1.2 查询参数3.1.3 数据提交 3.2 Promise3.2.1 Promise 使用步骤3.2.2 Promise 状态3.2.3 Promise 和 XHR 应用小案例 3.3 封装简易 axios3.3.1 核心封装代码3.3.2 支持传递查询参数3.3.3 支持传递请求体数据 Ajax…...
el-tree通过default-expand-all动态控制展开/折叠
1、如下图通过勾选框动态控制展开/折叠,全选/清空 2、实现方式如下:定义key,监听checked2修改treeKey,重新渲染tere;附加全选和清空。 <div class"tree"><el-checkbox v-model"checked1"…...
基于Bsdiff差分算法的汽车OTA升级技术研究(学习)
摘要 针对汽车OTA整包升级时,用户下载时间长,升级时间长,设备服务器端压力大等问题,本文提出了一种基于Bsdiff差分算法的汽车OTA升级技术。该算法能够对比新旧版本的差异,进行差分文件下载,减少软件包的下…...
如何使用CSS实现一个纯CSS的滚动条样式?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现自定义滚动条样式⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门  bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
