> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# Compilation 钩子

Compilation 钩子是 Rspack 插件的主要扩展方式，为开发者提供了介入构建流程各阶段的能力。

本文档列举了 Rspack 中可用的 Compilation 钩子、它们的触发时机、参数以及使用示例。

:::tip
查看 [Compilation](/zh/api/javascript-api/compilation.md) 了解更多关于 Compilation 对象的信息。
:::

:::info
Rspack 的主要编译逻辑运行在 Rust 侧。出于稳定性、性能、架构等因素，在使用钩子时，Rust 侧编译对象传输到 JavaScript 侧后，对 JavaScript 侧的修改不会被同步到 Rust 侧。因此绝大部分钩子为“只读”。
:::

## Overview


## `buildModule`

只读
在模块被构建之前调用。

- **类型：** `SyncHook<[Module]>`
- **参数：**
  - `Module`：模块实例


Module.ts

## `executeModule`

只读
若存在编译期执行模块，将在模块被执行时调用。

- **类型：** `SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>`
- **参数：**
  - `ExecuteModuleArgument`：模块运行参数
  - `ExecuteModuleContext`：模块运行上下文


ExecuteModuleArgument.ts

ExecuteModuleContext.ts

## `succeedModule`

只读
在模块成功构建后调用。

- **类型：** `SyncHook<[Module]>`
- **参数：**
  - `Module`：模块实例


Module.ts

## `finishModules`

只读
当所有模块都没有错误地构建完成时调用。

- **类型：** `AsyncSeriesHook<[Iterable<Module>]>`
- **参数：**
  - `Iterable<Module>`：模块实例的可迭代对象


Module.ts

## `optimizeModules`

只读
在模块优化阶段开始时调用。

- **类型：** `SyncBailHook<[Iterable<Module>]>`
- **参数：**
  - `Iterable<Module>`：模块实例的可迭代对象


Module.ts

## `seal`

停止接收新模块并开始优化前触发。

- **类型：** `SyncHook<[]>`

## `afterOptimizeModules`

只读
在模块优化完成之后调用。

- **类型：** `SyncHook<[Iterable<Module>]>`
- **参数：**
  - `Iterable<Module>`：模块实例的可迭代对象


Module.ts

## `optimizeTree`

只读
在优化依赖树之前调用。

- **类型：** `AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>`
- **参数：**
  - `Iterable<Chunk>`：Chunk 实例的可迭代对象
  - `Iterable<Module>`：模块实例的可迭代对象


Chunk.ts

Module.ts

## `optimizeChunkModules`

只读
在树优化之后，chunk 模块优化开始时调用。

- **类型：** `AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>]>`
- **参数：**
  - `Iterable<Chunk>`：Chunk 实例的可迭代对象
  - `Iterable<Module>`：模块实例的可迭代对象


Chunk.ts

Module.ts

## `additionalTreeRuntimeRequirements`

在树运行时依赖计算完成后调用。

- **类型：** `SyncHook<[Chunk, Set<RuntimeGlobals>]>`
- **参数：**
  - `Chunk`：Chunk 实例
  - `Set<RuntimeGlobals>`：运行时依赖集合

可通过修改运行时依赖集合以添加额外的内置运行时模块：

```js title="rspack.config.mjs"
export default {
  entry: './index.js',
  plugins: [
    {
      apply(compiler) {
        const { RuntimeGlobals } = compiler.rspack;
        compiler.hooks.thisCompilation.tap('CustomPlugin', (compilation) => {
          compilation.hooks.additionalTreeRuntimeRequirements.tap(
            'CustomPlugin',
            (_, set) => {
              // 添加访问 compilation 哈希值的运行时模块
              set.add(RuntimeGlobals.getFullHash);
            },
          );
        });
      },
    },
  ],
};
```

```js title="index.js"
// 将打印 compilation 的哈希值
console.log(__webpack_require__.h);
```

## `runtimeRequirementInTree`

在根据运行时依赖以添加运行时模块时调用。

- **类型：** `HookMap<SyncBailHook<[Chunk, Set<RuntimeGlobals>]>>`
- **参数：**
  - `Chunk`：Chunk 实例
  - `Set<RuntimeGlobals>`：运行时依赖集合

可通过修改运行时依赖集合以添加额外的内置运行时模块，也可通过 [`compilation.addRuntimeModule`](/zh/api/javascript-api/compilation.md#addruntimemodule) 添加自定义运行时模块：

```js title="rspack.config.mjs"
export default {
  entry: './index.js',
  plugins: [
    {
      apply(compiler) {
        const { RuntimeGlobals, RuntimeModule } = compiler.rspack;
        class CustomRuntimeModule extends RuntimeModule {
          constructor() {
            super('custom');
          }

          generate() {
            const compilation = this.compilation;
            return `
            __webpack_require__.mock = function(file) {
              return ${RuntimeGlobals.publicPath} + "/subpath/" + file;
            };
          `;
          }
        }

        compiler.hooks.thisCompilation.tap('CustomPlugin', (compilation) => {
          compilation.hooks.runtimeRequirementInTree
            .for(RuntimeGlobals.ensureChunkHandlers)
            .tap('CustomPlugin', (chunk, set) => {
              // 添加访问 publicPath 的运行时模块
              set.add(RuntimeGlobals.publicPath);
              // 添加自定义运行时模块
              compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
            });
        });
      },
    },
  ],
};
```

```js title="index.js"
// 将打印 "/subpath/index.js"
console.log(__webpack_require__.mock('index.js'));
```

## `runtimeModule`

在运行时模块被添加后调用。

- **类型：** `SyncHook<[RuntimeModule, Chunk]>`
- **参数：**
  - `RuntimeModule`：运行时模块
  - `Chunk`：Chunk 实例

可通过 `source` 字段修改该运行时模块生成的代码。

```js title="rspack.config.mjs"
export default {
  plugins: [
    {
      apply(compiler) {
        const { RuntimeGlobals } = compiler.rspack;
        compiler.hooks.compilation.tap('CustomPlugin', (compilation) => {
          compilation.hooks.runtimeModule.tap(
            'CustomPlugin',
            (module, chunk) => {
              if (module.name === 'public_path' && chunk.name === 'main') {
                const originSource = module.source.source.toString('utf-8');
                module.source.source = Buffer.from(
                  `${RuntimeGlobals.publicPath} = "/override/public/path";\n`,
                  'utf-8',
                );
              }
            },
          );
        });
      },
    },
  ],
};
```

```js title="index.js"
// 将打印 "/override/public/path"
console.log(__webpack_require__.p);
```


RuntimeModule.ts

## `processAssets`

在产物输出之前进行修改产物。

- **类型：** `AsyncSeriesHook<Assets>`
- **hook 参数：**
  - `name: string` — 插件的名称
  - `stage: Stage` — 要处理的阶段（参考 [Process assets stages](#process-assets-stages)）
- **参数：**
  - `Assets: Record<string, Source>`: 一个对象，其中 key 是 asset 的路径名，值是由 [Source](https://github.com/webpack/webpack-sources#source) 表示的 asset 数据。


Source.ts

### Process assets 示例

- 在 `PROCESS_ASSETS_STAGE_ADDITIONAL` 阶段输出一个新的 asset：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  const { Compilation } = compiler.rspack;
  compilation.hooks.processAssets.tap(
    {
      name: 'MyPlugin',
      stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
    },
    (assets) => {
      const { RawSource } = compiler.rspack.sources;
      const source = new RawSource('This is a new asset!');
      compilation.emitAsset('new-asset.txt', source);
    },
  );
});
```

- 更新一个已经存在的 asset：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  const { Compilation } = compiler.rspack;
  compilation.hooks.processAssets.tap(
    {
      name: 'MyPlugin',
      stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
    },
    (assets) => {
      const asset = assets['foo.js'];
      if (!asset) {
        return;
      }

      const { RawSource } = compiler.rspack.sources;
      const oldContent = asset.source();
      const newContent = oldContent + '\nconsole.log("hello world!")';
      const source = new RawSource(newContent);

      compilation.updateAsset(assetName, source);
    },
  );
});
```

- 移除一个 asset：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  const { Compilation } = compiler.rspack;
  compilation.hooks.processAssets.tap(
    {
      name: 'MyPlugin',
      stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
    },
    (assets) => {
      const assetName = 'unwanted-script.js';
      if (assets[assetName]) {
        compilation.deleteAsset(assetName);
      }
    },
  );
});
```

### Process assets stages

下面是支持的 stage 列表，Rspack 会按由上至下的顺序依次执行这些 stages，请根据你需要进行的操作来选择合适的 stage。

- `PROCESS_ASSETS_STAGE_ADDITIONAL` — 在编译中添加额外的 asset。
- `PROCESS_ASSETS_STAGE_PRE_PROCESS` — asset 进行了基础的预处理。
- `PROCESS_ASSETS_STAGE_DERIVED` — 从现有 asset 中派生新的 asset。
- `PROCESS_ASSETS_STAGE_ADDITIONS` — 为现有的 asset 添加额外的内容，例如 banner 或初始代码。
- `PROCESS_ASSETS_STAGE_OPTIMIZE` — 以通用的方式优化现有 asset。
- `PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT` — 优化现有 asset 的数量，例如，进行合并操作。
- `PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY` — 优化现有 asset 的兼容性，例如添加 polyfills 或者 vendor prefixes。
- `PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE` — 优化现有 asset 的大小，例如进行压缩或者删除空格。
- `PROCESS_ASSETS_STAGE_DEV_TOOLING` — 为 asset 添加开发者工具，例如，提取 source map。
- `PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE` — 将 asset 内联到其他 asset 中来优化现有 asset 数量。
- `PROCESS_ASSETS_STAGE_SUMMARIZE` — 整理现有 asset 列表。
- `PROCESS_ASSETS_STAGE_OPTIMIZE_HASH` — 优化 asset 的 hash 值，例如，生成基于 asset 内容的真实 hash 值。
- `PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER` — 优化已有 asset 的转换操作，例如对 asset 进行压缩，并作为独立的 asset。
- `PROCESS_ASSETS_STAGE_ANALYSE` — 分析已有 asset。
- `PROCESS_ASSETS_STAGE_REPORT` — 创建用于上报的 asset。

## `afterProcessAssets`

只读
在 [processAssets](#processassets) hook 无错误执行后调用。

- **类型：** `SyncHook<Assets>`
- **参数：**
  - `Assets: Record<string, Source>`：产物资源映射表


Source.ts

- **示例：**

```js
compilation.hooks.afterProcessAssets.tap('MyPlugin', (assets) => {
  console.log('assets', Object.keys(assets));
});
```

## `afterSeal`

只读
在 seal 阶段结束后调用。

- **类型：** `AsyncSeriesHook<[]>`

## `chunkHash`

只读
触发来为每个 chunk 生成 hash。

- **类型：** `SyncHook<[Chunk, Hash]>`
- **参数：**
  - `Chunk`：Chunk 实例
  - `Hash`：Chunk 哈希实例


Chunk.ts

Hash.ts

## `chunkAsset`

只读
一个 chunk 中的一个 asset 被添加到 compilation 时调用。

- **类型：** `SyncHook<[Chunk, string]>`
- **参数：**
  - `Chunk`：Chunk 实例
  - `string`：产物文件名


Chunk.ts

## `childCompiler`

只读
创建子 compiler 之后调用。

- **类型：** `SyncHook<[Compiler, string, number]>`
- **参数：**
  - `Compiler`：子编译实例：
  - `string`：子编译名称
  - `number`：子编译索引


Compiler.ts

## `statsPreset`

只读
当使用预设 stats 配置时触发。接收一个 stats 配置对象，当插件管理 stats 预设配置时，它应当在配置对象上仔细地修改，而非直接替换整个配置对象。

- **类型：** `SyncHook<[Partial<StatsOptions>, CreateStatsOptionsContext]>`
- **参数：**
  - `Partial<StatsOptions>`：Stats 配置
  - `CreateStatsOptionsContext`：Stats 上下文

以如下插件为例：

```js
compilation.hooks.statsPreset.for('my-preset').tap('MyPlugin', (options) => {
  if (options.all === undefined) options.all = true;
});
```

该插件确保对于预设 `"my-preset"`，如果 `all` 选项未定义，则默认为 `true`。


StatsOptions.ts

CreateStatsOptionsContext.ts

## `statsNormalize`

只读
此钩子用于将选项对象转换为便于后续钩子使用的格式。它还确保缺失的选项被设置为默认值。

- **类型：** `SyncHook<[Partial<StatsOptions>, CreateStatsOptionsContext]>`
- **参数：**
  - `Partial<StatsOptions>`：Stats 配置
  - `CreateStatsOptionsContext`：Stats 上下文

以如下插件为例：

```js
compilation.hooks.statsNormalize.tap('MyPlugin', (options) => {
  if (options.myOption === undefined) options.myOption = [];

  if (!Array.isArray(options.myOption)) options.myOptions = [options.myOptions];
});
```

在这个插件中，如果 `myOption` 缺失，会将其设置为 `[]`。此外，它确保 `myOption` 始终是一个数组，即使它最初被定义为单个值。


StatsOptions.ts

CreateStatsOptionsContext.ts

## `statsFactory`

只读
此钩子提供了对 `StatsFactory` 的访问，以调用其钩子。该类用于构造 Stats 对象。

- **类型：** `SyncHook<[StatsFactory, StatsOptions]>`
- **参数：**
  - `StatsFactory`：Stats 工厂实例，详见 [Stats Factory 钩子](/zh/api/plugin-api/stats-hooks.md#statsfactory)
  - `StatsOptions`：Stats 配置


StatsFactory.ts

StatsOptions.ts

## `statsPrinter`

只读
此钩子提供了对 `StatsPrinter` 的访问，以调用其钩子。该类用于打印 Stats 信息。

- **类型：** `SyncHook<[StatsPrinter, StatsOptions]>`
- **参数：**
  - `StatsPrinter`：Stats 打印实例，详见 [Stats Printer 钩子](/zh/api/plugin-api/stats-hooks.md#statsprinter)
  - `StatsOptions`：Stats 配置


StatsPrinter.ts

StatsOptions.ts