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

# Compiler

Compiler 是 Rspack 内部的核心对象，当你调用 Rspack 的 [JavaScript API](https://rspack.rs/zh/api/javascript-api/index.md) 或 [CLI](https://rspack.rs/zh/api/cli.md) 时，都会创建一个 Compiler 实例。

它提供了 [run](#run) 和 [watch](#watch) 等方法来启动构建，同时暴露了丰富的 [Compiler 钩子](https://rspack.rs/zh/api/plugin-api/compiler-hooks.md)，使 Rspack 插件能够干预构建的各个阶段。

## Compiler 对象方法

### run

启动一次编译流程，编译流程完成或因错误中止时触发回调。

```ts
function run(
  callback: (
    error: Error, // 仅包含构建器相关错误，如配置错误等，不包含编译错误
    stats: Stats, // 编译过程中产生的信息
  ) => void,
  options?: {
    modifiedFiles?: ReadonlySet<string>; // 本次编译包含的被修改的文件
    removedFiles?: ReadonlySet<string>; // 本次编译包含的被删除的文件
  },
): void;
```

:::warning

如果你需要多次调用同一个 `compiler` 对象的 `run` 方法，请注意以下事项：

1. 该 API 不支持并发编译操作。在启动新的编译任务之前，必须在 `compiler.run` 的回调函数中调用 `compiler.close()` 并等待其执行完成，之后才能进行下一次 `compiler.run` 调用。若同时运行多个编译进程，可能会导致输出文件产生不可预期的结果。
2. Rspack 的缓存失效检测机制依赖于 `modifiedFiles` 和 `removedFiles` 参数。在启用缓存的情况下，如果你使用了自定义的 watcher 来监听文件变化，需要通过 `options` 参数将这两个值传递给 Rspack。

:::

```js
compiler.run((err, stats) => {
  // 处理构建器错误
  handleCompilerError(err);
  // 处理编译错误
  handleModuleErrors(stats.toJson().errors);
  // 处理构建结果
  handleBuildResult(stats);
  // 结束本次编译
  compiler.close((closeErr) => {
    // 重新启动一次编译
    compiler.run((err, stats) => {});
  });
});
```


Stats.ts

### watch

启动持续监听，在文件变化后自动启动一次编译流程，每次编译流程完成或因错误中止时触发回调。

```ts
function watch(
  watchOptions: WatchOptions, // 启动监听的配置
  handler: (error: Error, stats: Stats) => void, // 每次编译流程完成或因错误中止时触发回调
): Watching; // 监听控制实例
```

:::warning 警告
这个 API 一次仅支持一个监听。请在 `compiler.watch` 回调中调用 `compiler.close`，并等待它完成后再次执行 `compiler.watch`。并发编译将破坏输出文件。
:::

```js
const watching = compiler.watch(
  {
    aggregateTimeout: 300,
    poll: undefined,
  },
  (err, stats) => {
    // 处理构建结果
    handleBuildResult(stats);
  },
);
```

Watching 对象提供如下方法：

- `watch`:
  - **类型：** `(files: Iterable<string>, dirs: Iterable<string>, missing: Iterable<string>): void`
  - **用途：** 添加需要被监听的文件和目录
- `invalidate`:
  - **类型：** `(callback: () => void): void`
  - **用途：** 立即结束本轮监听，并以当前记录的文件变更启动一次编译流程，不会停止整个监听器。
- `suspend`:
  - **类型：** `(): void`
  - **用途：** 进入仅监听状态，不会启动新的编译流程
- `resume`:
  - **类型：** `(): void`
  - **用途：** 退出仅监听状态，并以当前记录的文件变更启动一次编译流程
- `close`:
  - **类型：** `(callback: () => void): void`
  - **用途：** 停止整个监听器


WatchOptions.ts

Stats.ts

### close

关闭当前构建器，在此期间处理低优先级任务，如缓存等。

```ts
function close(
  callback: (err: Error) => void, // 关闭完成后回调
): void;
```

### getInfrastructureLogger

创建一个不与 Compilation 关联的全局[日志对象](https://rspack.rs/zh/api/javascript-api/logger.md)，用于打印全局信息。

```ts
function getInfrastructureLogger(name: string): Logger;
```


Logger.ts

### getCache

创建一个缓存对象，以在构建流程中共享数据。

```ts
function getCache(name: string): CacheFacade;
```


Cache.ts

### purgeInputFileSystem

停止对文件系统的读取循环，它内部包含定时器，可能会导致 `compiler.close` 后进程依然无法退出。

```ts
function purgeInputFileSystem(): void;
```

### createChildCompiler

创建并返回一个子 `Compiler`，可以为其指定输出选项和额外插件。钩子和插件的继承规则见 [compilation.createChildCompiler](https://rspack.rs/zh/api/javascript-api/compilation.md#createchildcompiler)。

```ts
function createChildCompiler(
  compilation: Compilation,
  compilerName: string,
  compilerIndex: number,
  outputOptions: OutputOptions,
  plugins?: (RspackPluginInstance | Falsy)[],
): Compiler;
```


Compilation.ts

OutputOptions.ts

RspackPlugin.ts

### runAsChild

启动子 Compiler 的构建流程，会进行一次完整的构建流程并生成产物。

```ts
function runAsChild(
  callback(
    err: Error, // 子 Compiler 执行的构建器错误
    entries: Chunk[], // 子 Compiler 执行产生的 Chunk 信息
    compilation: Compilation, // 子 Compiler 所创建的 Compilation 对象
  ): void;
): void;
```


Chunk.ts

Compilation.ts

### isChild

当前是否为子 Compiler。

```ts
function isChild(): boolean;
```

## Compiler 对象属性

### hooks

详见 [Compiler 钩子](https://rspack.rs/zh/api/plugin-api/compiler-hooks.md)

### rspack

- **类型：** `typeof rspack`

获取当前的 `@rspack/core` 的导出，以此来获取关联的内部对象。当你无法直接引用 `@rspack/core`，或者存在多个 Rspack 实例时很有用。

一个常见的例子是在 Rspack 插件中获取 [sources](https://rspack.rs/zh/api/javascript-api/index.md#sources-%E5%AF%B9%E8%B1%A1) 对象：

```js
const { RawSource } = compiler.rspack.sources;
const source = new RawSource('console.log("Hello, world!");');
```

### webpack

- **类型：** `typeof rspack`

等同于 `compiler.rspack`，该属性用于兼容 webpack 插件。

如果你开发的 Rspack 插件需要兼容 webpack，可以使用该属性代替 `compiler.rspack`。

```js
console.log(compiler.webpack === compiler.rspack); // true
```

### name

- **类型：** `string`

获取名称：

- 对于根 Compiler 等同于 [`name`](https://rspack.rs/zh/config/other-options.md#name)
- 对于子 Compiler 时为 `createChildCompiler` 传入的值
- 对于 MultiCompiler 且为 KV 形式时为 Key 的值

### context

当前的项目根目录：

- 通过 `new Compiler` 时为传入的值
- 通过 `rspack({})` 等创建时同于 [context 配置](https://rspack.rs/zh/config/context.md)

### root

- **类型：** `Compiler`

获取根 Compiler 实例。

### options

- **类型：** `RspackOptionsNormalized`

获取根 Compiler 所使用的完整[构建配置](https://rspack.rs/zh/config/index.md)。

### target

- **类型：**

```ts
type CompilerTarget = {
  // ECMAScript 版本
  esVersion?: number | null;
  // 包含版本号的平台名称
  targets?: Record<string, string> | null;
};
```

从 [target](https://rspack.rs/zh/config/target.md) 配置中推断出。这对需要访问目标环境信息的插件和 loader 作者非常有用。

- `targets`: 包含平台名称及其版本的对象（例如：`{ 'chrome': '87', 'firefox': '78', 'node': '18' }`）。
- `esVersion`: ECMAScript 版本号（例如：`5`, `2015`, `2022`）。

例如，在插件中访问 `compiler.target`：

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.initialize.tap('ExamplePlugin', () => {
      const { targets, esVersion } = compiler.target ?? {};
      console.log(targets, esVersion);
    });
  }
}
```

或是在自定义 loader 中访问 `compiler.target`：

```js title="my-loader.js"
export default function myLoader(source) {
  const options = this.getOptions();
  const compilerTarget = this._compiler.target ?? {};
  // 使用用户指定的 targets，或者回退到 Rspack 推断出的 targets
  const targets = options.targets ?? compilerTarget.targets;
  // 需要时回退到 Rspack 推断出的 ECMAScript 版本
  const ecmaVersion = options.ecmaVersion ?? compilerTarget.esVersion;
  // 使用 targets 进行转换...
  return transform(source, { targets, ecmaVersion });
}
```

### watchMode

- **类型：** `boolean`

是否通过 watch 启动。

### watching

- **类型：** `Watching`

获取 watch 启动下的监听控制对象，详见 [watch 方法](#watch)

### running

- **类型：** `boolean`

当前是否正在执行构建流程。

### inputFileSystem

- **类型：** `InputFileSystem`

获取用于从文件系统读取的代理对象，其内部有缓存等优化，以降低对同一文件的重复读取。


InputFileSystem.ts

### outputFileSystem

- **类型：** `OutputFileSystem`

获取用于输出到文件系统的代理对象，默认使用 `fs`。


OutputFileSystem.ts

### watchFileSystem

- **类型：** `WatchFileSystem`

获取用于持续监听文件/目录变化的代理对象，提供一个 `watch` 方法来启动监听，并在回调中传入变更和移除的项目。


WatchFileSystem.ts

## MultiCompiler

`MultiCompiler` 可以让 Rspack 同时执行多份配置。如果传给 Rspack 的 JavaScript API 的配置为多个配置对象构成的数组，Rspack 会创建多个 compiler 实例，并且在所有 compiler 执行完毕后调用回调方法。

```js
import { rspack } from '@rspack/core';

rspack(
  [
    { entry: './index1.js', output: { filename: 'bundle1.js' } },
    { entry: './index2.js', output: { filename: 'bundle2.js' } },
  ],
  (err, stats) => {
    process.stdout.write(stats.toString() + '\n');
  },
);
```

也可以通过 `new MultiCompiler` 创建：

```js
const compiler1 = new Compiler({/* */});
const compiler2 = new Compiler({/* */});

new MultiCompiler([compiler1, compiler2]);

new MultiCompiler([compiler1, compiler2], {
  parallelism: 1, // 控制最大并行数量
});

new MultiCompiler({
  name1: compiler1,
  name2: compiler2,
});
```

MultiCompiler 也提供了部分 Compiler 的方法和属性。

### MultiCompiler 方法

#### setDependencies

指定 compiler 之间的依赖关系，以 `compiler.name`作为标识，以此保证 compiler 执行顺序。

```ts
setDependencies(compiler: Compiler, dependencies: string[]): void;
```

#### validateDependencies

检测 compiler 之间的依赖关系是否合法，若成环或缺失会触发回调。

```ts
validateDependencies(
  callback: (err: Error) => void; // 错误时回调，若多个错误会回调多次
): boolean
```

#### run

根据依赖关系执行各个 compiler 的 `run` 方法，启动编译流程。

```ts
run(
  callback: (err: Error, stats: MultiStats) => void,
  options?: {
    modifiedFiles?: ReadonlySet<string>; // 本次编译包含的被修改的文件
    removedFiles?: ReadonlySet<string>; // 本次编译包含的被删除的文件
  },
): void;
```

#### watch

根据依赖关系执行各个 compiler 的 `watch` 方法，启动持续监听，在文件变化后自动启动一次编译流程。

```ts
function watch(
  watchOptions: WatchOptions | WatchOptions[],
  handler: (err: Error, stats: MultiStats) => void,
): MultiWatching;
```

#### close

执行各个 compiler 的 `close` 方法，关闭构建器，并在此期间处理低优先级任务，如缓存等。

```ts
close(callback: (err: Error) => void): void;
```

#### purgeInputFileSystem

执行各个 compiler 的 `purgeInputFileSystem`，停止对文件系统的读取循环。

```ts
purgeInputFileSystem(): void;
```

#### getInfrastructureLogger

创建一个不与 Compilation 关联的全局[日志对象](https://rspack.rs/zh/api/javascript-api/logger.md)，用于打印全局信息。

```ts
getInfrastructureLogger(name: string): Logger;
```

> 等同于 `compilers[0].getInfrastructureLogger()`


Logger.ts

### MultiCompiler 属性

#### compilers

- **类型：** `Compiler[]`

获取包含的所有 Compiler 实例。


Compiler.ts

#### options

只读
- **类型：** `RspackOptionsNormalized[]`

获取各个 Compiler 所使用的完整[构建配置](https://rspack.rs/zh/config/index.md)。

#### inputFileSystem

只写
- **类型：** `InputFileSystem`

为各个 Compiler 设置用于从文件系统读取的代理对象。


InputFileSystem.ts

#### outputFileSystem

只写
- **类型：** `OutputFileSystem`

为各个 Compiler 设置用于输出到文件系统的代理对象。


OutputFileSystem.ts

#### watchFileSystem

只写
- **类型：** `WatchFileSystem`

为各个 Compiler 设置用于持续监听文件/目录变化的代理对象。


WatchFileSystem.ts

#### running

- **类型：** `boolean`

当前是否正在执行构建流程。
