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. io--文件内容的复制

    public class CopyTextTest_2 {  private static final int BUFFER_SIZE = 1024;  public static void main ...

  2. java String拼接的方法选择及性能分析

    String 拼接的方法选择 在拼接静态字符串时,尽量用 +,因为通常编译器会对此做优化,如: String test = "this " + "is " + ...

  3. Python的编码详解

    一. 编码介绍 计算机只能处理数字(最底层的0和1),如果要处理文本,就必须将文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以一个字节能表示的最大整数就 ...

  4. POJ3074 Sudoku

    POJ3074 Sudoku 与POJ2676相比,这一题搜索时每一步都找到最好确定的点进行枚举 对于每行.每列.每个九宫格,都分别用一个9位二进制数保存还有那些数还可以填 对于每个位置,将其所在行. ...

  5. 动态渲染可编辑单元格的Table

    一.问题描述 问题是这样的,后台传了xArr = [x1, x2,...,xn]和yArr = [y1, y2, ..yn]两个数组,前端要渲染出表格并且可以填写每个单元格的值,然后按照一定数据结构保 ...

  6. Kettle根据表输入的SQL脚本返回创建表的SQL脚本

    其中[物料分组]节点就是表输入,里面可以构建SQL查询.那么怎么把生成的数据插入到目标表中?并且构建目标表的结构呢? 目标表结构就在[表输出]栏位 点击[SQL],就可以看见生成目标表结构的脚本

  7. Service与BoardcastReceive

    开发service需要两个步骤: 1.定义一个继承Service的子类 2.在AndroidMainfest.xml文件中配置该Service. Service与Activity都是从Context派 ...

  8. 【算法笔记】B1019 数字黑洞

    1019 数字黑洞 (20 分)   给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字.一直 ...

  9. Hystrix - 踩坑回忆

    1.Unable to connect to Command Metric Stream 异常 Finchley版本使用Hystrix存在此问题.网上常规解决思路: @Bean public Serv ...

  10. python创建目录并更改权限的代码

    如下代码段是关于python创建目录并更改权限的代码. import os os.mkdir("foo", 0666)