tapable
webpack本质上是一种事件流机制,工作流程就是将各个插件串联起来,实现得核心就是tapable,核心得原理也是类似于node.js得events库,依赖于发布订阅模式。
查看源码,编译模块compiler.js。
tapable引入了各种钩子,有同步有异步得,靠他们串联
写个简单得插件,注册事件 启动事件,这里因为我是新建项目,本来想用两个文件写得import 无法解析,所以暂时写在一个文件上,也可以去配置下setting.json,不过问题不大。
同步钩子 包括了同步并发,和同步串行
class SyncHook {
constructor(args) {
// 任务存放
this.tasks = [];
}
tap(name, task) {
this.tasks.push(task);
}
call(...args) {
// 发布订阅
// this.tasks.forEach((item) => {
// item.events(...args);
// });
// 瀑布模式
let [first, ...others] = this.tasks;
let re = first(...args);
others.reduce((a, b) => {
return b(a);
}, re);
}
}
let hooks = new SyncHook();
hooks.tap("aaa", function (name) {
console.log("aaa事件:", name);
return "aaa111事件";
});
hooks.tap("ddd", function (name) {
console.log("ddd事件:", name);
return "ddd事件";
});
hooks.tap("ccc", function (name) {
console.log("ccc事件:", name);
return "ccc事件";
});
hooks.tap("ffff", function (name) {
console.log("ffff事件:", name);
});
hooks.call("yangjie");
异步钩子:异步并发 和异步串行
class asyncPromise {
constructor(args) {
// 任务存放
this.tasks = [];
}
tapAsync(name, task) {
this.tasks.push(task);
}
tapPromise(name, task) {
this.tasks.push(task);
}
callAsync(...args) {
// return new Promise((reslove, reject) => {
// let index = 0;
// this.tasks.forEach((task) =>
// task(...args).then(() => {
// index++;
// if (index == this.tasks.length) {
// reslove();
// }
// })
// );
// });
// 并行
// this.proArr = this.tasks.map((task) => task(...args));
// return Promise.all(this.proArr);
// 串行
return new Promise((re, je) => {
let [first, ...others] = this.tasks;
others.reduce((a, b) => {
return a.then((res) => b(res));
}, first(...args));
});
}
}
let hooks = new asyncPromise();
hooks.tapPromise("aaa", function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("aaa事件:", name);
resolve("aa得传值");
}, 1000);
});
});
hooks.tapPromise("ddd", function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("ddd事件:", name);
resolve("ddd得传值");
}, 1000);
});
});
hooks.tapPromise("ccc", function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("ccc事件:", name);
resolve();
}, 1000);
});
});
hooks.callAsync("yangjie").then((res) => {
console.log("res:end", res);
});