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事件流插件的更多相关文章

  1. .26-浅析webpack源码之事件流make(1)

    compilation事件流中,依然只是针对细节步骤做事件流注入,代码流程如图: // apply => this-compilation // apply => compilation ...

  2. .15-浅析webpack源码之WebpackOptionsApply模块-plugin事件流总览

    总体过了一下后面的流程,发现Compiler模块确实不适合单独讲解,这里继续讲解后面的代码: compiler.options = new WebpackOptionsApply().process( ...

  3. .21-浅析webpack源码之事件流this-compilation

    上一节生成Compilation实例后,添加了一些属性,随后触发this-compilation事件流,如下: Compiler.prototype.newCompilation = (params) ...

  4. .29-浅析webpack源码之doResolve事件流(1)

    在上一节中,最后返回了一个resolver,本质上就是一个Resolver对象: resolver = new Resolver(fileSystem); 这个对象的构造函数非常简单,只是简单的继承了 ...

  5. Wookmark-jQuery-master 瀑布流插件

    Wookmark-jQuery-master 瀑布流插件使用介绍,含个人测试DEMO 要求 必备知识 本文要求基本了解 Html/CSS,  JavaScript/JQuery. 开发环境 Dream ...

  6. .31-浅析webpack源码之doResolve事件流(2)

    放个流程图: 这里也放一下request对象内容,这节完事后如下(把vue-cli的package.json也复制过来了): /* { context: { issuer: '', compiler: ...

  7. .30-浅析webpack源码之doResolve事件流(1)

    这里所有的插件都对应着一个小功能,画个图整理下目前流程: 上节是从ParsePlugin中出来,对'./input.js'入口文件的路径做了处理,返回如下: ParsePlugin.prototype ...

  8. .27-浅析webpack源码之事件流make(2)

    上一节跑到了NormalModuleFactory模块,调用了原型方法create后,依次触发了before-rsolve.factory.resolver事件流,这节从resolver事件流开始讲. ...

  9. .25-浅析webpack源码之事件流compilation(3)

    这一节跑下一批plugin. compiler.apply( new EnsureChunkConditionsPlugin(), new RemoveParentModulesPlugin(), n ...

随机推荐

  1. 集成 jpush-react-native 常见问题汇总 (iOS 篇)

    给 iOS 应用添加推送功能是一件比较麻烦的事情,本篇文章收集了集成 jpush-react-native 的常见问题,目的是为了帮助用户更好地排查问题 1. 收不到推送 确保是在真机上测试,而不是在 ...

  2. python3的enumerate函数

    enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中.

  3. Beginning and Ending the Speech

    Beginning and Ending the Speech Just as musical plays need appropriate beginnings and endings, so do ...

  4. 条目二十八《正确理解由reverse_iterator的base()成员函数所产生的iterator的用法》

    条目二十八<正确理解由reverse_iterator的base()成员函数所产生的iterator的用法> 迭代器的种类一共有四种,上面已经说过了.这里就不再次写出来. 这一个条目主要是 ...

  5. Linux-Web应用服务性能测试初探

    一.服务端与客户端的准备工作 对于服务器最想要的数据就是,每秒支持的并发数,以及相应的内存CPU使用情况. 服务端需要设置最大打开描述符的限制(以支持创建大量的socket),配置socket参数.客 ...

  6. wifi测距

    #include "ESP8266WiFi.h" #include "math.h" //d = 10^(A-(abs(rssi)) / (10 * n)) 信 ...

  7. C# 文件读写Helper类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  8. 进阶篇:3)面向制造的设计DFM

    本章目的:正确认识面向制造的设计-DFM. 1.DFM概念 DFM有两种描述是作者比较认可的. ①面向制造的设计(design for manufacturing简称DFM):指产品设计需要满足产品制 ...

  9. 【算法笔记】B1034 有理数四则运算

    1034 有理数四则运算 (20 分)   本题要求编写程序,计算 2 个有理数的和.差.积.商. 输入格式: 输入在一行中按照 a1/b1 a2/b2 的格式给出两个分数形式的有理数,其中分子和分母 ...

  10. L2-2 小字辈 (25 分)

    本题给定一个庞大家族的家谱,要请你给出最小一辈的名单. 输入格式: 输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号.随后第二行 ...