tapable事件流插件
tapable
Webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable,webpack中最核心的负责编译的Compiler和负责创建bundle的Compilation都是Tapable的实例
const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
AsyncParallelHook,
AsyncParallelBailHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook
} = require("tapable");
SyncHook
串行同步执行,不关心返回值
//钩子可以在stage和其他钩子之间穿插钩子
const hook = new SyncHook()
const calls = [];
hook.tap("A",() => calls.push("A"))
hook.tap({
name:"B",
before:"A"
},() => calls.push("B"))
calls.length = 0
hook.call()
hook.tap({
name:"C",
before:["A","B"]
},() => calls.push("C"))
calls.length = 0
hook.call()
hook.tap({
name:"D",
before:"B"
},() => calls.push("D"))
calls.length = 0;
hook.call()
hook.tap({
name:"E",
stage:3
},() => calls.push("E"))
hook.tap({
name:"F",
stage:1
},() => calls.push("F"))
calls.length = 0;
hook.call()
console.log(calls)
//创建同步钩子
const h0 = new SyncHook(["arg1"]);
h0.tap("A",(name) => {
console.log(name)
})
h0.tap("B",(name) => {
console.log(name)
})
h0.call('plus',24)
SyncBailHook
串行同步执行,有一个返回值不为null则跳过剩下的逻辑
const h1 = new SyncBailHook(["a"]);
h1.tap("A",a => {console.log(a) ;return a})
h1.tap("B",a => console.log(a))
h1.call(1)
SyncWaterfallHook
const h1 = new SyncWaterfallHook(['name'])
h1.tap("A",(name) => {
console.log(name,1)
})
h1.tap("B",(data) => {
console.log(data,2)
return 2
})
h1.tap("C",(data) => {
console.log(data,3)
return 3
})
h1.call('plus',24)
SyncLoopHook
监听函数返回true表示继续循环,返回undefine表示结束循环
const h1 = new SyncLoopHook(['name'])
let count = 0
h1.tap('A',name => (
count < 3 ?
(count++,console.log(name),true)
:undefined
))
h1.call(
'plus'
)
AsyncParallelHook
异步并行钩子
const h1 = new AsyncParallelHook(['name'])
h1.tap('A',() => console.log(1))
h1.tap('B',() => console.log(2))
h1.tap('C',() => console.log(3))
h1.callAsync('test',err => {
console.log(err)
})
const h1 = new AsyncParallelHook(['name'])
console.time('count')
h1.tapAsync('A',(name,callback) => {
setTimeout(() => (console.log(1),callback()),2000)
})
h1.tapAsync('B',(name,callback) => {
setTimeout(() => (console.log(2),callback()),1000)
})
h1.tapAsync('C',(name,callback) => {
setTimeout(() => (console.log(3),callback()),3000)
})
h1.callAsync('test',err => {
console.log(err)
console.timeEnd('count')
})
const h1 = new AsyncParallelHook(['name'])
console.time('count')
h1.tapPromise('A',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(1),resolve()),2000)
})
))
h1.tapPromise('B',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(2),resolve()),1000)
})
))
h1.tapPromise('C',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(3),resolve()),3000)
})
))
h1.callAsync('test',err => {
console.log(err)
console.timeEnd('count')
})
AsyncParallelBailHook
带保险带异步执行钩子
let h1=new AsyncParallelBailHook(['name']);
console.time('count');
h1.tap('A',function(name){
console.log(1);
return "Wrong";
});
h1.tap('B',function(name){
console.log(2);
});
h1.tap('C',function(name){
console.log(3);
});
h1.callAsync('test',err=>{
console.log(err);
console.timeEnd('count');
});
let h1=new AsyncParallelBailHook(['name']);
console.time('count');
h1.tapAsync('A',function(name,callback){
console.log(1);
return "Wrong";
});
h1.tapAsync('B',function(name,callback){
console.log(2);
});
h1.tapAsync('C',function(name.callback){
console.log(3);
});
h1.callAsync('test',err=>{
console.log(err);
console.timeEnd('count');
});
const h1 = new AsyncParallelBailHook(['name'])
console.time('count')
h1.tapPromise('A',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(1),resolve()),2000)
})
))
h1.tapPromise('B',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(2),resolve()),1000)
})
))
h1.tapPromise('C',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(3),resolve()),3000)
})
))
h1.callAsync('test',err => {
console.log(err)
console.timeEnd('count')
})
AsyncSeriesHook
异步串行钩子
let h1 = new AsyncSeriesHook(['name']);
console.time('cost');
h1.tap('A',function(name){
console.log(1);
});
h1.tap('B',function(name){
console.log(2);
});
h1.tap('C',function(name){
console.log(3);
});
h1.callAsync('test',err=>{
console.log(err);
console.timeEnd('cost');
});
let h1 = new AsyncSeriesHook(['name']);
console.time('cost');
h1.tapAsync('A',function(name,callback){
setTimeout(function(){
console.log(1);
callback()
},1000)
});
h1.tapAsync('B',function(name,callback){
setTimeout(function(){
console.log(2);
callback()
},2000)
});
h1.tapAsync('C',function(name,callback){
setTimeout(function(){
console.log(3);
callback()
},3000)
});
h1.callAsync('test',err=>{
console.log(err);
console.timeEnd('cost');
});
let h1=new AsyncSeriesHook(['name']);
console.time('cost');
h1.tapPromise('A',function(name){
return new Promise(function(resolve){
setTimeout(function(){
console.log(1);
resolve();
},1000)
});
});
h1.tapPromise('B',function(name,callback){
return new Promise(function(resolve){
setTimeout(function(){
console.log(2);
resolve();
},2000)
});
});
h1.tapPromise('C',function(name,callback){
return new Promise(function(resolve){
setTimeout(function(){
console.log(3);
resolve();
},3000)
});
});
h1.promise('test').then(data=>{
console.log(data);
console.timeEnd('cost');
});
AsyncSeriesBailHook
let h1 = new AsyncSeriesBailHook(['name']);
console.time('cost');
h1.tap('A',function(name){
console.log(1);
return "Wrong";
});
h1.tap('B',function(name){
console.log(2);
});
h1.tap('C',function(name){
console.log(3);
});
h1.callAsync('test',err=>{
console.log(err);
console.timeEnd('cost');
});
let h1 = new AsyncSeriesBailHook(['name']);
console.time('cost');
h1.tapAsync('A',function(name,callback){
setTimeout(function(){
console.log(1);
callback('wrong')
},1000)
});
h1.tapAsync('B',function(name,callback){
setTimeout(function(){
console.log(2);
callback()
},2000)
});
h1.tapAsync('C',function(name,callback){
setTimeout(function(){
console.log(3);
callback()
},3000)
});
h1.callAsync('test',err=>{
console.log(err);
console.timeEnd('cost');
});
const h1 = new AsyncSeriesBailHook(['name'])
console.time('count')
h1.tapPromise('A',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(1),reject()),2000)
})
))
h1.tapPromise('B',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(2),resolve()),1000)
})
))
h1.tapPromise('C',(name,callback) => (
new Promise((resolve,reject) => {
setTimeout(() => (console.log(3),resolve()),3000)
})
))
h1.promise('test',err => {
console.log(err)
console.timeEnd('count')
},err => {
console.log(err);
console.timeEnd('cost');
})
AsyncSeriesWaterfallHook
let {AsyncSeriesWaterfallHook} = require('tapable');
let h1 = new AsyncSeriesWaterfallHook(['name']);
console.time('cost');
h1.tap('1',function(name,callback){
console.log(1);
});
h1.tap('2',function(data){
console.log(2,data);
});
h1.tap('3',function(data){
console.log(3,data);
});
queue.callAsync('test',err=>{
console.log(err);
console.timeEnd('cost');
});
let h1 = new AsyncSeriesWaterfallHook(['name']);
console.time('cost');
h1.tapAsync('1',function(name,callback){
setTimeout(function(){
console.log(1);
callback(null,1);
},1000)
});
h1.tapAsync('2',function(data,callback){
setTimeout(function(){
console.log(2);
callback(null,2);
},2000)
});
h1.tapAsync('3',function(data,callback){
setTimeout(function(){
console.log(3);
callback(null,3);
},3000)
});
h1.callAsync('test',(err,data)=>{
console.log(err,data);
console.timeEnd('cost');
});
let h1 = new AsyncSeriesWaterfallHook(['name']);
console.time('cost');
h1.tapPromise('1', function (name) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log(name, 1);
resolve(1);
}, 1000);
});
});
h1.tapPromise('2', function (data) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log(data, 2);
resolve(2);
}, 2000);
});
});
h1.tapPromise('3', function (data) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log(data, 3);
resolve(3);
}, 3000);
});
});
h1.promise('test').then(err => {
console.timeEnd('cost');
});
tapable
class MyPlugin {
constructor(){
this.hooks = {
add:new SyncHook(['name'])
}
}
}
const myPlugin = new MyPlugin()
myPlugin.hooks.add.tap('add',(name) => {
console.log(name)
})
myPlugin.hooks.add.tap('minus',(name) => {
console.log(name)
})
myPlugin.hooks.add.call('plus')
tapable事件流插件的更多相关文章
- .26-浅析webpack源码之事件流make(1)
compilation事件流中,依然只是针对细节步骤做事件流注入,代码流程如图: // apply => this-compilation // apply => compilation ...
- .15-浅析webpack源码之WebpackOptionsApply模块-plugin事件流总览
总体过了一下后面的流程,发现Compiler模块确实不适合单独讲解,这里继续讲解后面的代码: compiler.options = new WebpackOptionsApply().process( ...
- .21-浅析webpack源码之事件流this-compilation
上一节生成Compilation实例后,添加了一些属性,随后触发this-compilation事件流,如下: Compiler.prototype.newCompilation = (params) ...
- .29-浅析webpack源码之doResolve事件流(1)
在上一节中,最后返回了一个resolver,本质上就是一个Resolver对象: resolver = new Resolver(fileSystem); 这个对象的构造函数非常简单,只是简单的继承了 ...
- Wookmark-jQuery-master 瀑布流插件
Wookmark-jQuery-master 瀑布流插件使用介绍,含个人测试DEMO 要求 必备知识 本文要求基本了解 Html/CSS, JavaScript/JQuery. 开发环境 Dream ...
- .31-浅析webpack源码之doResolve事件流(2)
放个流程图: 这里也放一下request对象内容,这节完事后如下(把vue-cli的package.json也复制过来了): /* { context: { issuer: '', compiler: ...
- .30-浅析webpack源码之doResolve事件流(1)
这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...
- .27-浅析webpack源码之事件流make(2)
上一节跑到了NormalModuleFactory模块,调用了原型方法create后,依次触发了before-rsolve.factory.resolver事件流,这节从resolver事件流开始讲. ...
- .25-浅析webpack源码之事件流compilation(3)
这一节跑下一批plugin. compiler.apply( new EnsureChunkConditionsPlugin(), new RemoveParentModulesPlugin(), n ...
随机推荐
- JMeter—断言
断言用来对服务器的响应数据做验证,常用的断言是响应断言,支持正则表达式. 一.BeanShell Assertion 用来访问JMeter的属性: log对象,可以利用此对象写日志 SampleRes ...
- POJ3322Bloxorz I
POJ3322 Bloxorz I 暴搜,next数组与处理一下(小技巧) #include <cstdio> #include <iostream> #include < ...
- loj2497 [PA2017]Banany(动态淀粉质)
link 给定一棵树,点有点权,边有边权,你每次修改一个点点权或者是修改一个边边权 你一开始在1号点,你每次改节点之后你需要移动到另一个节点,满足这个节点权值减去路径长度最大(下一次从这个节点移动)如 ...
- NOIP模拟题汇总(加厚版)
\(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...
- 用 gdb 和 qemu 调试 grub
因为qemu内置了gdbserver,所以我们可以用gdb调试qemu虚拟机上执行的代码,而且不受客户机系统限制. 以下内容是我调试 grub 0.97 时的一份笔记. 准备 qemu, gdb,以及 ...
- (USB HID) Configuration Descriptor
最近完成了HID的基本收發,使用的配置用了2個Endpoint,把一些特別重要要的地方紀錄下來 整個Configuration 分成4大部分 : 1. Configuration 2. Interfa ...
- ubuntu 报错 libcublas.so.8.0
在qt程序中使用yolo时报错: ./conjugateGradientPrecond: error while loading shared libraries: libcublas.so.8.0: ...
- CRS无法随操作系统自动启动
1.环境说明 一套RedHat7.5上安装的11.2.0.4 RAC,进行正常的系统维护,重启主机后发现GI集群一直无法启动. 2.问题分析 (1).查看GI集群的OHASD进程的日志,发现操作系 ...
- C/C++中创建(带头结点、不带头结点的)单链表
1.带头结点的单链表(推荐使用带头结点的单链表)(采用尾插法) 了解单链表中节点的构成 从上图可知,节点包含数据域和指针域,因此,在对节点进行定义时,我们可以如下简单形式地定义: /* 定义链表 */ ...
- 性能测试工具Jmeter13-Jmeter跨线程组调用token
1.正则表达式或者json提取器(我是用json提取器提取的),提取token 2.添加后置处理器BeanShell PostProcessor,然后输入以下函数 3.添加HTTP信息头管理器,写入函 ...