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 ...
随机推荐
- Python——深拷贝和浅拷贝
深拷贝.浅拷贝 1. 浅拷贝 浅拷贝是对于一个对象的顶层拷贝 import copy a = [[1, 2], 3] b = copy.copy(a) print(id(a)) print(id(b) ...
- 关于:maven项目中pom.xml文件添加依赖无法自动搜索的问题
用的是eclipse 1.Window------>Show View------->Maven Repositories(这个选项一般不直接显示,而在others里面) 2.操作完毕后会 ...
- Objective-C语法基础:面向对象编程特点的总结
1.类的声明与实现 Objective-C类的声明要写在@interface 与 @end之间,实现要写在@implementation 与 @end之间 2.类的-方法和+方法 类的-方法即类的实例 ...
- Codeforces Round #556 (Div. 2) - C. Prefix Sum Primes(思维)
Problem Codeforces Round #556 (Div. 2) - D. Three Religions Time Limit: 1000 mSec Problem Descripti ...
- Python全栈-magedu-2018-笔记12
第三章 - Python 内置数据结构 字典dict key-value键值对的数据的集合 可变的.无序的.key不重复 字典dict定义 初始化 d = dict() 或者 d = {} dict( ...
- JavaWeb学习笔记(二十一)—— 监听器Listener
一.监听器概述 JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSession和 ServletRequest等域对 ...
- Q791 自定义字符串排序
字符串S和 T 只包含小写字符.在S中,所有字符只会出现一次. S 已经根据某种规则进行了排序.我们要根据S中的字符顺序对T进行排序.更具体地说,如果S中x在y之前出现,那么返回的字符串中x也应出现在 ...
- Python爬虫常用之登录(二) 浏览器模拟登录
浏览器模拟登录的主要技术点在于: 1.如何使用python的浏览器操作工具selenium 2.简单看一下网页,找到帐号密码对应的框框,要知道python开启的浏览器如何定位到这些 一.使用selen ...
- WIndows下 Pycharm 配置Anaconda和TensorFlow
1安装PyCharm 前提安装Python,然后去官网下载PyCharm 2 安装Anaconda 在官网下载Anaconda,并安装 下载好之后就跟安装一般的软件没啥区别,选择自己安装的文件夹,下一 ...
- 3dsmax2016卸载/安装失败/如何彻底卸载清除干净3dsmax2016注册表和文件的方法
3dsmax2016提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装3dsmax2016失败提示3dsmax2016安装未完成,某些产品无法安装,也有时候想重新 ...