Webpack 里面的插件是怎么实现的?
https://v4.webpack.docschina.org/api/plugins/#tapable
https://vip.yidengfe.com/ques/info/357#text-1-5-0
https://juejin.cn/post/6844903789804126222
插件机制核心库: tapable(钩子hook+tap方法)
自定义插件
- 创建一个插件函数, 定义apply方法, 指定一个绑定到webpack自身的钩子函数
- apply函数, 处理webpack内部实例的的定数据
函数尾部, 调用webpack提供的回调函数
class MyExampleWebpackPlugin {
// 定义 `apply` 方法
apply(compiler) {
// 指定要追加的事件钩子函数
compiler.hooks.compile.tapAsync(
'afterCompile',
(compilation, callback) => {
console.log('This is an example plugin!');
console.log('Here’s the `compilation` object which represents a single build of assets:', compilation);
// 使用 webpack 提供的 plugin API 操作构建结果
compilation.addModule(/* ... */);
callback();
}
);
}
}
tapable
tapable 是一个类似于nodejs 的EventEmitter 的库, 主要是控制钩子函数的发布与订阅。
几种hook(异步、同步)
- BasicHook:执行每一个,不关心函数的返回值
- SyncHook
- AsyncSeriesHook
- AsyncParallelHook
- BailHook:顺序执行 Hook,遇到第一个结果result!==undefined则返回,不再继续执行
- SyncBailHook
- AsyncSeriseBailHook
- AsyncParallelBailHook
- WaterfallHook:类似于 reduce,如果前一个 Hook 函数的结果 result !== undefined,则 result 会作为后一个 Hook 函数的第一个参数。
- SyncWaterfallHook
- AsyncSeriesWaterfallHook
- LoopHook:不停的循环执行 Hook,直到所有函数结果 result === undefined。
- SyncLoopHook
- AsyncSeriseLoopHook
简单demo
yarn add tapable
const { SyncHook } = require('tapable');
// 创建一个同步 Hook,指定参数
const hook = new SyncHook(['arg1', 'arg2']);
// 注册
hook.tap('a', function (arg1, arg2) {
console.log('a');
});
hook.tap('b', function (arg1, arg2) {
console.log('b');
});
hook.call(1, 2);
// a
// b