const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
AsyncParallelHook,
AsyncParallelBailHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook
} = require("tapable");
用法
All Hook constructors take one optional argument, which is a list of argument names as strings.
class Car {
constructor() {
this.hooks = {
accelerate: new SyncHook(["newSpeed"]),
brake: new SyncHook(),
calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"])
}
}
}
const muCar = new Car()
//注册监听
//同步钩子
myCar.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`));
myCar.hooks.brake.tap("WarningLampPlugin", () => warningLamp.on());
//异步钩子
myCar.hooks.calculateRoutes.tapPromise("GoogleMapsPlugin", (source, target, routesList) => {
return google.maps.findRoute(source, target).then(route => {
routesList.add(route);
});
});
钩子注册(钩入)方式
- 同步
- tap
- 异步
- tap
- tapPromise
- tapAsync
Hooks type
每个钩子都能监听一个或多个函数,函数如何执行取决于钩子的类型
- hook 基础钩子
- bail hook 只要有一个handler有返回值,剩下handler不执行
- waterfall hook 上一个handler的返回值当做下一个handler的入参
- loop hook 循环 只要钩子有返回值,不停loop
- sync hook 同步
- async hook 异步
- Async series 异步串行
- Async parallel 异步并行
拦截器
每个钩子都有拦截器,每个拦截器接收call,tap,register,loop,context五个属性
const {
SyncLoopHook,
} = require("../lib/index")
class Test {
constructor(){
this.hooks = {
test: new SyncLoopHook(["name"]),
};
}
}
const objTest = new Test()
objTest.hooks.test.intercept({
//当钩子使用call调用
call: (name) => {
console.log("call");
},
//当插件进入钩子的时候调用(注册),Tap对象无法更改
tap: (Tap) => {
console.log("tap");
},
//当钩子循环的时候调用
loop: (name)=>{
console.log('loop');
},
//钩子使用tap调用,并且可以修改Tap对象
register: (Tap) => {
console.log("register");
},
});
objTest.hooks.test.tap('testPlugin',(name)=>{
console.log(name);
})
objTest.hooks.test.call('test')
//输出结果如下
register
call
loop
tap
test
//Tap对象结构
interface Tap {
name: string,
type: string
fn: Function,
stage: number,
context: boolean,
before?: string | Array
}
webpack中如何使用Tapable
-
hooks均继承自hook(lib/Hook.js)
-
Tap tapAsync tappromise会把handler丢入到数组中。
-
call callAsync promise会按照相应的顺序去执行数组中的handler
//以SyncHook为例 精简版 lass SyncHookCodeFactory extends HookCodeFactory { content({ onError, onDone, rethrowIfPossible }) { return this.callTapsSeries({ onError: (i, err) => onError(err), onDone, rethrowIfPossible }); } } const factory = new SyncHookCodeFactory(); const COMPILE = function(options) { factory.setup(this, options); return factory.create(options); };
-
call
、callAsync
、promise
最终会调用每个hook的COMPILE
方法 -
COMPILE方法会实例化继承自HookCodeFactory的相应类并调用HookCodeFactory的create方法
-
create
方法用new Function(‘a’,‘b’,‘return a+b’)方式去创建每个handler的执行函数字符串问:为啥用new Function去创建函数?
答:函数入参和函数体会根据入参的长度而动态生成,这样你可以根据实际情况来控制传入参数的个数,并且函数也只处理这几个入参。
-
-