webpack插件机制Tapable

126 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

  • Webpack 本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是 Tapable,webpack 中最核心的负责编译的 Compiler 和负责创建 bundle 的 Compilation 都是 Tapable 的实例
  • 通过事件和注册和监听,触发 webpack 生命周期中的函数方法

Tapable是webpack打包的核心工具, 暴露了tap,tapAsync,tapPromise方法来实现hook封装调用。在webpack打包的过程中一些hook注入事件。

1. tapable分类

同步异步分类 Hook 类型可以分为同步Sync和异步Async,异步又分为并行和串行

按同步异步分类

  • 同步: SyncHook, SyncBailHook, SyncWaterfallHook,SyncLoopHook
  • 异步: AsyncParalleHook, AsyncParalleBailHook, AsyncSeriesHook, AsyncSeriesBailHook,AsyncSeriesWaterfallHook

按照返回值分类

1.1 Basic 执行每一个事件函数,不关心函数的返回值,有 SyncHook、AsyncParallelHook、AsyncSeriesHook

  • SyncHook
  • AsyncSeriesHook
  • AsyncParalleHook

1.2 Bail 执行每一个事件函数,遇到第一个结果 result !== undefined 则返回,不再继续执行。有:SyncBailHook、AsyncSeriesBailHook, AsyncParallelBailHook

  • SyncBailHook
  • AsyncParalleBailHook
  • AsyncSeriesBailHook

1.3 Waterfall 如果前一个事件函数的结果 result !== undefined,则 result 会作为后一个事件函数的第一个参数,有 SyncWaterfallHook,AsyncSeriesWaterfallHook

  • SyncWaterfallHook
  • AsyncSeriesWaterfallHook

1.4 Loop 不停的循环执行事件函数,直到所有函数结果 result === undefined,有 SyncLoopHook 和 AsyncSeriesLoopHook

  • SyncLoopHook

2. plugin的配置,

//plugin都在plugins里面注册和实例化, plugin类实现apply方法,传入compiler,
// 会在webpack打包流程初始阶段循环调用插件的apply方法去注册事件
module.exports = {
  mode: 'development',
  devtool:false,
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin({
      template:'./src/index.html'
    }),
    new DonePlugin(),
    new ArchivePlugin()
  ]
}


  //3. webpack打包流程初始化阶段,获取所有配置后,加载所有配置的插件将compiler传进去
  const { plugins } = finalOptions;
  for (let plugin of plugins) {
    plugin.apply(compiler);
  }

2.1 简单的plugin

  • 插件是一个类
  • 类上有一个apply的实例方法
  • apply的参数是compiler
class DonePlugin { 
    constructor(options) {
        this.options = options; 
    } 
    apply(compiler) {
    } 
 }
  • compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。
  • compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

3. compiler 钩子

Compiler 模块是 webpack 的主要引擎,它通过 CLI 或者 Node API 传递的所有选项创建出一个 compilation 实例。 它扩展(extends)自 Tapable 类,用来注册和调用插件。 大多数面向用户的插件会首先在 Compiler 上注册。

compiler.hooks.someHook.tap('MyPlugin', (params) => {
  /* ... */
});

常用的compiler 钩子,compilation 钩子可参考官网的例子:

compilation 钩子