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提供的回调函数

    1. class MyExampleWebpackPlugin {
    2. // 定义 `apply` 方法
    3. apply(compiler) {
    4. // 指定要追加的事件钩子函数
    5. compiler.hooks.compile.tapAsync(
    6. 'afterCompile',
    7. (compilation, callback) => {
    8. console.log('This is an example plugin!');
    9. console.log('Here’s the `compilation` object which represents a single build of assets:', compilation);
    10. // 使用 webpack 提供的 plugin API 操作构建结果
    11. compilation.addModule(/* ... */);
    12. callback();
    13. }
    14. );
    15. }
    16. }

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

image.png

简单demo

  1. yarn add tapable
  2. const { SyncHook } = require('tapable');
  3. // 创建一个同步 Hook,指定参数
  4. const hook = new SyncHook(['arg1', 'arg2']);
  5. // 注册
  6. hook.tap('a', function (arg1, arg2) {
  7. console.log('a');
  8. });
  9. hook.tap('b', function (arg1, arg2) {
  10. console.log('b');
  11. });
  12. hook.call(1, 2);
  13. // a
  14. // b