tapable
webpack本质上是一种事件流的机制,他的工作流程就是将各个插件串联起来,而实现这一切的核心就是tapable,
tapable有点类似于nodejs的events库,核心原理也是依赖于发布订阅模式:
继承了很多插件,同步的和异步的
tapable库中有3中注册方法 tap(同步注册)、tabAsync(回调cb)、tabPromise(注册是promise)
调用的三种方法 call、 callAsync、 promise
tapable异步钩子使用及原理
本章讲述异步钩子
异步钩子又分为异步并行和异步串行钩子:
AsyncParralleHook
当所有异步事件并行执行完成后,执行回调函数
使用方法:
// 异步钩子,串行、并行(需要等待所有并发的异步事件执行后再执行回调方法)
let {
AsyncParallelHook} = require('tapable');
class Lesson {
constructor() {
this.index = 0;
this.hooks = {
arch: new AsyncParallelHook(['name']),
}
}
// 注册监听函数(注册方法分为tap, tapAsync)
tap() {
this.hooks.arch.tapAsync('node', (name, cb) => {
setTimeout(() => {
console.log('node', name);
cb();
}, 1000);
});
this.hooks.arch.tapAsync('react', (name, cb) => {
setTimeout(() => {
console.log('react', name);
cb();
}, 1000);
});
}
start() {
this.hooks.arch.callAsync('zhangfeng', function () {
console.log('end');
});
}
}
let les = new Lesson();
les.tap(); // 注册这两个事件
les.start(); // 启动钩子
// => node zhangfeng
// => react node还需要加强学习
实现原理:
class AsyncParralleHook {
// 钩子是同步的
constructor(args) {
// args => ['name']
this.tasks = [];
}
callAsync(...args) {
let finalCallback = args.pop();// 拿出最终的参数
let index = 0;
let done = () => {
// 类似 Promise.all
index ++;
if (index === this.tasks.length) {
finalCallback();
}
};
this.tasks.forEach(task => {
task(...args, done);
});
}
tapAsync(name, task) {
this.tasks.push(task);
}
}
let hook = new AsyncParralleHook(['name']);
hook.tapAsync('react', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb();
}, 1000);
});
hook.tapAsync('node', function(name, cb) {
setTimeout(() => {
console.log('node', name);
cb();
}, 1000);
});
hook.callAsync('zhangfeng', function () {
console.log('所有方法执行结束');
});
使用promise方式实现AsyncParallelHook
使