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

# Compiler 钩子

Compiler hooks 允许 Rspack 插件在特定阶段介入构建流程。它们代表了从初始化到资源输出的各个生命周期阶段。

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

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

## Overview


## `environment`

在编译器准备环境时，初始化插件之后调用。

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

## `afterEnvironment`

当编译器环境准备完成后，在 `environment` 钩子后直接调用。

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

## `entryOption`

在 Rspack 选项中的 [`entry`](/zh/config/entry.md) 被处理过之后调用。

- **类型：** `SyncBailHook<[string, EntryNormalized]>`
- **参数：**
  - `string`: 等同于 [`context`](/zh/config/context.md) 配置
  - `EntryNormalized`: 处理后的 [`entry`](/zh/config/entry.md) 配置

## `afterPlugins`

在初始化内部插件完成之后调用。

- **类型：** `SyncHook<[Compiler]>`
- **参数：**
  - `Compiler`: 当前 Compiler 实例


Compiler.ts

## `afterResolvers`

resolver 设置完成之后触发。

- **类型：** `SyncHook<[Compiler]>`
- **参数：**
  - `Compiler`: 当前 Compiler 实例


Compiler.ts

## `initialize`

当编译器被初始化时调用。

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

## `beforeRun`

在开始执行一次构建之前调用。

:::note
这个钩子仅在调用 [compiler.run()](/zh/api/javascript-api/index.md#compilerrun) 时触发（对应 `rspack build` 命令），在监听模式（watch mode）下不会执行。在监听模式下，你可以使用 [watchRun](#watchrun) 钩子。
:::

- **类型：** `AsyncSeriesHook<[Compiler]>`
- **参数：**
  - `Compiler`: 当前 Compiler 实例


Compiler.ts

- **示例：** 同步操作

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.beforeRun.tap('ExamplePlugin', (compiler) => {
      console.log('Build is about to start...');
    });
  }
}
```

- **示例：** 异步操作

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.beforeRun.tapPromise('ExamplePlugin', async (compiler) => {
      console.log('Build is about to start...');

      await someAsyncOperation();
    });
  }
}
```

## `run`

在开始执行一次构建时调用。

:::note
这个钩子仅在调用 [compiler.run()](/zh/api/javascript-api/index.md#compilerrun) 时触发（对应 `rspack build` 命令），在监听模式（watch mode）下不会执行。在监听模式下，你可以使用 [watchRun](#watchrun) 钩子。
:::

- **类型：** `AsyncSeriesHook<[Compiler]>`
- **参数：**
  - `Compiler`: 当前 Compiler 实例


Compiler.ts

- **示例：** 同步操作

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.run.tap('ExamplePlugin', (compiler) => {
      console.log('Build start...');
    });
  }
}
```

- **示例：** 异步操作

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.run.tapPromise('ExamplePlugin', async (compiler) => {
      console.log('Build start...');

      await someAsyncOperation();
    });
  }
}
```

## `watchRun`

在监听模式下，开始执行一次构建时调用。

你可以通过 `compiler.modifiedFiles` 和 `compiler.removedFiles` 获取变更的文件路径和删除的文件路径。

:::note
这个钩子仅在调用 [compiler.watch()](/zh/api/javascript-api/index.md#compilerwatch) 时触发，在非监听模式下不会执行。在非监听模式下，你可以使用 [run](#run) 或 [beforeRun](#beforerun) 钩子。
:::

- **类型：** `AsyncSeriesHook<[Compiler]>`
- **参数：**
  - `Compiler`: 当前 Compiler 实例


Compiler.ts

- **示例：** 同步操作

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.watchRun.tap('ExamplePlugin', (compiler) => {
      const { modifiedFiles, removedFiles } = compiler;
      if (modifiedFiles) {
        console.log('Changed files:', Array.from(modifiedFiles));
      }
      if (removedFiles) {
        console.log('Removed files:', Array.from(removedFiles));
      }
    });
  }
}
```

- **示例：** 异步操作

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.watchRun.tapPromise('ExamplePlugin', async (compiler) => {
      await someAsyncOperation();
    });
  }
}
```

## `beforeCompile`

在编译参数创建后执行插件。

- **类型：** `AsyncSeriesHook<[CompilationParams]>`
- **参数：**
  - `params`：编译参数，包含 [normal module factory](/zh/api/plugin-api/normal-module-factory-hooks.md) 和 [context module factory](/zh/api/plugin-api/context-module-factory-hooks.md)。

```ts
type CompilationParams = {
  normalModuleFactory: NormalModuleFactory;
  contextModuleFactory: ContextModuleFactory;
};
```

## `compile`

在一个新的 [compilation 对象](/zh/api/javascript-api/compilation.md) 被创建之前调用。

- **类型：** `SyncHook<[CompilationParams]>`
- **参数：**
  - `params`：与 [beforeCompile](#beforecompile) 接收的相同编译参数。

## `thisCompilation`

在创建 compilation 对象时调用，用于获取当前的 compilation 对象。

你可以通过 `compilation` 参数来访问 compilation 对象的属性，或是注册 [compilation hooks](/zh/api/plugin-api/compilation-hooks.md)。

- **类型：** `SyncHook<[Compilation, CompilationParams]>`
- **参数：**
  - `compilation`: 创建的 [compilation 对象](/zh/api/javascript-api/compilation.md)
  - `params: CompilationParams`：本次编译使用的模块工厂，包含 `normalModuleFactory` 和 `contextModuleFactory` 属性。


Compilation.ts

- **示例：**

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.thisCompilation.tap('ExamplePlugin', (compilation) => {
      console.log('compilation created:', compilation);

      compilation.hooks.processAssets.tap('ExamplePlugin', (assets) => {
        console.log('Generated assets:', Object.keys(assets));
      });
    });
  }
}
```

## `compilation`

在 compilation 对象创建之后调用，用于获取当前的 compilation 对象。

你可以使用 `compilation` 参数来访问 compilation 对象的属性，或是注册 [compilation hooks](/zh/api/plugin-api/compilation-hooks.md)。

`compilation` 钩子的调用晚于 [thisCompilation](#thiscompilation) 钩子，并且 `thisCompilation` 钩子不会被复制到 child compiler 中，而 `compilation` 钩子会被复制到 child compiler 中。

- **类型：** `SyncHook<[Compilation, CompilationParams]>`
- **参数：**
  - `compilation`: 创建的 [compilation](/zh/api/javascript-api/compilation.md) 对象
  - `params: CompilationParams`：本次编译使用的模块工厂，包含 `normalModuleFactory` 和 `contextModuleFactory` 属性。


Compilation.ts

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('ExamplePlugin', (compilation) => {
      console.log('compilation created:', compilation);

      compilation.hooks.processAssets.tap('ExamplePlugin', (assets) => {
        console.log('Generated assets:', Object.keys(assets));
      });
    });
  }
}
```

## `make`

在 make 阶段开始前调用，在 make 阶段会以 entry 为起点构建模块依赖图，并使用 loader 处理各个模块。

- **类型：** `AsyncParallelHook<[Compilation]>`
- **参数：**
  - `Compilation`: 当前 [Compilation](/zh/api/javascript-api/compilation.md) 对象


Compilation.ts

## `finishMake`

在 make 阶段结束后调用。在 make 阶段，Rspack 会以 entry 为起点构建模块依赖图，并使用 loader 处理各个模块，当这个过程完成时会触发此钩子。

- **类型：** `AsyncSeriesHook<[Compilation]>`
- **参数：**
  - `Compilation`: 当前 [Compilation](/zh/api/javascript-api/compilation.md) 对象


Compilation.ts

## `afterCompile`

在 compilation 完成并 seal 之后、Rspack 判断是否输出产物（[`shouldEmit`](#shouldemit)）之前调用。

此时产物已经生成并可以通过 `compilation.assets` 访问，但尚未写入输出目录，因此插件仍然可以在这里终止构建，而不会留下已写出的产物文件。

- **类型：** `AsyncSeriesHook<[Compilation]>`
- **参数：**
  - `Compilation`: 当前 [Compilation](/zh/api/javascript-api/compilation.md) 对象


Compilation.ts

## `shouldEmit`

在输出资源之前调用。返回 `false` 表示跳过资源输出，返回 `true` 表示输出资源；这两种返回值都会停止执行后续 tap。返回 `undefined` 或不返回值则继续执行下一个 tap。如果没有 tap 返回布尔值，Rspack 会输出资源。

- **类型：** `SyncBailHook<[Compilation], boolean | void>`
- **参数：**
  - `Compilation`: 当前 [Compilation](/zh/api/javascript-api/compilation.md) 对象


Compilation.ts

- **示例：**

```js
compiler.hooks.shouldEmit.tap('MyPlugin', (compilation) => {
  // 如果编译存在错误，则跳过资源输出。
  if (compilation.errors.length > 0) {
    return false;
  }
});
```

## `emit`

在产物输出到结果目录前执行。

- **类型：** `AsyncSeriesHook<[Compilation]>`
- **参数：**
  - `Compilation`: 当前 [Compilation](/zh/api/javascript-api/compilation.md) 对象


Compilation.ts

## `afterEmit`

输出产物到结果目录后执行。

- **类型：** `AsyncSeriesHook<[Compilation]>`
- **参数：**
  - `Compilation`: 当前 [Compilation](/zh/api/javascript-api/compilation.md) 对象


Compilation.ts

## `done`

当前 Compilation 处理完成时执行。

- **类型：** `AsyncSeriesHook<Stats>`
- **参数：**
  - `Stats`: 生成的 Stats 对象


Stats.ts

## `afterDone`

当前 Compilation 处理完成且 `done` 钩子调用之后执行。

- **类型：** `SyncHook<Stats>`
- **参数：**
  - `Stats`: 生成的 Stats 对象


Stats.ts

## `failed`

当前 Compilation 失败时调用。

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

## `invalid`

当监听模式下的编译因文件变更而失效时执行。这个 hook 不会被复制到 child compiler 中。

- **类型：** `SyncHook<[string | null, number]>`
- **参数：**
  - `fileName`: 失效的文件路径
  - `changeTime`: 失效的文件修改时间戳

在触发重新编译时，这个 hook 可以用于获取变更的文件路径和修改时间，例如：

```ts
compiler.hooks.invalid.tap('MyPlugin', (fileName, changeTime) => {
  console.log(`Changed file: ${fileName}, change time: ${changeTime}`);
});
```

## `watchClose`

停止监听时调用。

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

## `shutdown`

当前 Compiler 关闭时调用。

- **Type:** `AsyncSeriesHook<[]>`

## infrastructureLog

当基础设施日志被触发时调用，允许插件拦截、修改或处理日志消息。

此钩子提供了一种自定义 Rspack 基础设施日志的方法 - 你可以过滤特定的日志类型、添加自定义格式，或完全覆盖默认的日志行为。

如果钩子返回 `true`，将阻止默认的基础设施日志记录。如果返回 `undefined`，将继续执行默认的日志输出。

- **类型：** `SyncBailHook<[string, string, any[]], true | void>`
- **参数：**
  - `name`：logger 的名称
  - `type`：log 类型（例如 'log'、'warn'、'error' 等）
  - `args`：传递给 logger 方法的参数数组
- **示例：**

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.infrastructureLog.tap('MyPlugin', (name, type, args) => {
      // 自定义日志逻辑
      if (type === 'error') {
        console.error(`[${name}] ERROR:`, ...args);
        return true; // 阻止默认日志输出
      }

      // 让其他日志类型使用默认行为
      return undefined;
    });
  }
}
```

> 查看 [infrastructureLogging](/zh/config/infrastructure-logging.md) 了解更多关于基础设施日志的信息。
