返回

从 Tapable 源码解析 Webpack 事件流核心

前端

Tapable 是 Webpack 中一个重要的模块,它提供了事件流机制,使我们能够在不同的时机触发自定义事件。本文将带大家从源码的角度来深入剖析 Tapable 的实现,以了解它的工作原理和使用方法。

Tapable 源码解析

Tapable 的源码位于 webpack/lib/Tapable.js,它是一个类,主要提供了以下几个方法:

  • apply(): 用于应用插件。
  • callAsync(): 用于异步调用插件。
  • call(): 用于同步调用插件。
  • tap(): 用于注册一个插件。
  • tapAsync(): 用于异步注册一个插件。
  • tapPromise(): 用于注册一个返回 Promise 的插件。

其中,apply() 方法是 Tapable 的核心方法,它负责调用所有已注册的插件。它的实现如下:

apply(options) {
  const fn = this._createCallback(options);
  this._plugins.forEach((plugin) => {
    fn(plugin);
  });
}

apply() 方法首先调用 _createCallback() 方法来创建一个回调函数,然后遍历所有已注册的插件,并调用该回调函数。回调函数的实现如下:

_createCallback(options) {
  if (this.taps.length === 0) {
    return () => {};
  }

  if (options.async) {
    return (plugin) => {
      plugin.apply(options.args, (err, result) => {
        if (err) {
          this.applyPluginsBailResult("error", err);
          return;
        }
        this.applyPluginsAsyncSeriesBailResult("async", result);
      });
    };
  }

  if (options.promise) {
    return (plugin) => {
      plugin.apply(options.args).then(
        (result) => {
          this.applyPluginsAsyncSeriesBailResult("async", result);
        },
        (err) => {
          this.applyPluginsBailResult("error", err);
        }
      );
    };
  }

  return (plugin) => {
    plugin.apply(options.args);
  };
}

_createCallback() 方法根据 options 参数的不同,创建不同的回调函数。如果 options.async 为 true,则创建一个异步回调函数,该回调函数会在插件执行完毕后调用 applyPluginsAsyncSeriesBailResult() 方法。如果 options.promise 为 true,则创建一个返回 Promise 的回调函数,该回调函数会在插件执行完毕后调用 applyPluginsAsyncSeriesBailResult() 方法。否则,创建一个同步回调函数,该回调函数会在插件执行完毕后立即返回。

Tapable 使用示例

Tapable 的使用非常简单,我们只需要注册一个插件,然后调用 apply() 方法即可。例如,我们可以注册一个插件来监听 compilation 事件:

const webpack = require('webpack');

const compiler = webpack({
  plugins: [
    new webpack.CompilationPlugin({
      name: 'my-plugin',
      apply(compiler) {
        compiler.hooks.compilation.tap('my-plugin', (compilation) => {
          console.log('Compilation started!');
        });
      },
    }),
  ],
});

compiler.run();

当我们运行这个脚本时,我们会看到 "Compilation started!" 信息被打印到控制台。

总结

Tapable 是 Webpack 中一个重要的模块,它提供了事件流机制,使我们能够在不同的时机触发自定义事件。本文从源码的角度分析了 Tapable 的实现,并给出了一个使用示例。希望本文能够帮助您更好地理解 Tapable 的工作原理和使用方法。