> 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.

# Compilation

Compilation 对象是 Rspack 构建过程中的核心对象之一，每当 Rspack 执行构建时（包括监听模式下的重新构建），都会创建一个新的 Compilation 实例，它包含了当前构建的所有信息。

当前页面列举了 Compilation 对象上可用的方法和属性。你也可以参考 [Compilation 钩子](https://rspack.rs/zh/api/plugin-api/compilation-hooks.md) 了解 Compilation 对象提供的钩子。

:::warning 注意
在 Rspack 中，真实的 Compilation 运行在 Rust 侧，JavaScript Compilation 仅作为用于与 Rust Compilation 通信的**代理对象**。

因此，部分较为复杂的数据结构和方法将不会在 JavaScript Compilation 上支持，同时**数据只读**且结构可能与 webpack 存在差异。
:::

## 获取 compilation 对象

你可以通过 [compiler.hooks.thisCompilation](https://rspack.rs/zh/api/plugin-api/compiler-hooks.md#thiscompilation) 或 [compiler.hooks.compilation](https://rspack.rs/zh/api/plugin-api/compiler-hooks.md#compilation) 钩子来获取当前的 compilation 对象。

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

    compiler.hooks.compilation.tap('ExamplePlugin', (compilation) => {
      console.log('compilation hook called:', compilation);
    });
  }
}
```

## Compilation 对象方法

### emitAsset

添加一个产物。允许使用相同文件名重复添加内容相同的产物。如果同名产物的内容不同，则会记录一个编译错误。如需替换已有产物，请使用 [updateAsset](#updateasset)。

```ts
emitAsset(
  filename: string, // 产物文件名
  source: Source, // 产物内容
  info?: AssetInfo // 产物信息对象
): void;
```

以下示例将添加一个 `asset-name.js` 的新产物且不会被压缩：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  const { RawSource } = compiler.rspack.sources;
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    const buffer = Buffer.from(
      'i am content of emit asset, do not minimize me',
    );
    const source = new RawSource(buffer, false);
    compilation.emitAsset('asset-name.js', source, {
      minimized: true,
    });
  });
});
```


Source.ts

AssetInfo.ts

### updateAsset

变更一个已经存在的产物的内容，如果产物不存在则会抛错。

```ts
updateAsset(
  filename: string, // 产物文件名
  source: Source | ((source: Source) => Source), // 变更后的产物内容 或 产物内容获取函数
  info?: // 变更后的产物信息 或 产物信息获取函数
    | AssetInfo
    | ((assetInfo: AssetInfo) => AssetInfo | undefined)
): void;
```

以下示例将 `main.js` 的产物内容替换：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  const { RawSource } = compiler.rspack.sources;
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    const updatedSource = new RawSource(`console.log("Updated");`);
    compilation.updateAsset('main.js', updatedSource, {
      // optional asset info...
    });
  });
});
```


Source.ts

AssetInfo.ts

### renameAsset

更改一个已经存在的产物的名称。

```ts
renameAsset(
  filename: string, // 产物文件名
  newFilename: string // 变更后的产物名
): void;
```

以下示例将 `main.js` 产物更名为 `my-asset-name.js`：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    compilation.renameAsset('main.js', 'my-asset-name.js');
  });
});
```

### deleteAsset

移除一个已经存在的产物。

```ts
deleteAsset(
  filename: string // 待移除的产物文件名
): void;
```

以下示例将移除名为 `no-need.js` 的产物：

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    compilation.deleteAsset('no-need.js');
  });
});
```

### getAssets

获取产物对象列表。

```ts
getAssets(): ReadonlyArray<{
  name: string; // 产物文件名
  source: Source; // 产物内容
  info: AssetInfo; // 产物信息
}>;
```

以下示例将打印所有产物的总体积大小：

```js
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    const assets = compilation.getAssets();
    const totalSize = assets.reduce(
      (total, asset) => total + asset.source.size(),
      0,
    );
    console.log(`total size: ${totalSize}`);
  });
});
```


Source.ts

AssetInfo.ts

### getAsset

获取指定名称的产物对象。

```ts
getAsset(
  name: string // 产物文件名
): Readonly<{
  name: string; // 产物文件名
  source: Source; // 产物内容
  info: AssetInfo; // 产物信息
}> | undefined;
```

以下示例将打印名为 `main.js` 的产物体积：

```js
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    const assetSize = compilation.getAsset('main.js')?.source.size();
    console.log(`main size: ${assetSize}`);
  });
});
```


Source.ts

AssetInfo.ts

### getPath

基于模板生成路径字符串，模板规则见 [文件名占位符](https://rspack.rs/zh/config/filename-placeholders.md)。

```ts
getPath(
  filename: Filename, // 路径模板
  data: PathData = {} // 生成数据
): string;
```

以下示例将替换模板中的占位符生成对应的路径：

```js
const path = compilation.getPath('[contenthash]-[fullhash].js', {
  contentHash: 'some1',
  hash: 'some2',
});
console.log(path); // "some1-some2.js"
```


Filename.ts

PathData.ts

### getPathWithInfo

基于模板生成路径字符串和资源信息，模板规则见 [文件名占位符](https://rspack.rs/zh/config/filename-placeholders.md)。

```ts
getPathWithInfo(
  filename: Filename, // 路径模板
  data: PathData = {} // 生成数据
): {
  path: string;
  info: AssetInfo;
};
```

以下示例将替换模板中的占位符生成对应的路径和资源信息：

```ts
const { path, info } = compilation.getPathWithInfo(
  '[contenthash]-[fullhash].js',
  {
    contentHash: 'some1',
    hash: 'some2',
  },
);
console.log(path); // "some1-some2.js"
console.log(info);
/* Object {
  immutable: true,
  minimized: false,
  fullhash: [ 'some2' ],
  chunkhash: [],
  contenthash: [ 'some1' ],
  development: false,
  hotModuleReplacement: false,
  related: {},
  extras: {}
} */
```


Filename.ts

PathData.ts

AssetInfo.ts

### getStats

返回当前编译的 Stats 对象。

```ts
getStats(): Stats;
```

以下示例将输出模块总数：

```js
compiler.hooks.emit.tap('MyPlugin', (compilation) => {
  const modules = compilation.getStats().toJson({ modules: true }).modules;
  console.log(`Total modules: ${modules.length}`);
});
```


Stats.ts

### createChildCompiler

创建并返回一个子 `Compiler`，可以为其指定输出选项和额外插件。子编译器会继承父编译器中符合条件的钩子回调和内置插件。

`make`、`compile`、`emit`、`afterEmit`、`invalid`、`done` 和 `thisCompilation` 钩子上的回调不会复制到子编译器。内置插件仅在支持子编译器继承时才会被继承。可以通过 `plugins` 参数为子编译器应用额外插件。

```ts
createChildCompiler(
  name: string, // 子编译器名称
  outputOptions: OutputNormalized, // 子编译所使用的 Output 配置对象
  plugins?: (RspackPluginInstance | Falsy)[] // 为子编译器额外添加的插件
): Compiler;
```

以下示例将以 `child-entry.js` 作为入口添加子编译，并将产物输出到 `dist/child` 中:

```js
compiler.hooks.make.tap('MyPlugin', (compilation) => {
  const childCompiler = compilation.createChildCompiler(
    'ChildCompiler',
    {
      path: 'dist/child',
    },
    [new compiler.rspack.EntryPlugin(compiler.context, './child-entry.js')],
  );
  childCompiler.compile((err, childCompilation) => {});
});
```


Compiler.ts

### addRuntimeModule

添加一个自定义的运行时模块。

```ts
addRuntimeModule(
  c: Chunk, // 运行时模块所在的 Chunk
  m: RuntimeModule, // 运行时模块的实例
): void;
```

以下代码添加一个运行时模块，该模块定义 `__webpack_require__.mock`，并添加到 `"main"` Chunk 中：

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

        class CustomRuntimeModule extends RuntimeModule {
          constructor() {
            super('custom');
          }

          generate() {
            const compilation = this.compilation;
            return `
            __webpack_require__.mock = function() {
              // ...
            };
          `;
          }
        }

        compiler.hooks.thisCompilation.tap('CustomPlugin', (compilation) => {
          compilation.hooks.runtimeRequirementInTree
            .for(RuntimeGlobals.ensureChunkHandlers)
            .tap('CustomPlugin', (chunk, set) => {
              if (chunk.name === 'main') {
                compilation.addRuntimeModule(chunk, new CustomRuntimeModule());
              }
            });
        });
      },
    },
  ],
};
```

实现自定义的运行时模块 Class 时，可覆盖如下方法/属性来控制其行为：

- 在构造器中传入 `name` 和 `stage` 参数来指定模块名称和插入的阶段
- 覆盖 `generate()` 方法以控制模块生成的代码
- 覆盖 `shouldIsolate()` 方法以控制模块是否包裹在 IIFE 当中
- 覆盖 `attach()` 方法以修改在模块被添加时的行为
- 修改其 `fullHash` 或 `dependentHash` 属性以控制模块是否可被缓存

### rebuildModule

重新构建指定模块。

```ts
rebuildModule(m: Module, f: (err: Error | null, m: Module | null) => void): void;
```

以下示例将重新构建结尾为 `a.js` 模块：

```js
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.finishModules.tapPromise('MyPlugin', async (modules) => {
    const oldModule = Array.from(modules).find((item) =>
      item.resource?.endsWith('a.js'),
    );
    if (!oldModule) {
      return;
    }

    await new Promise((resolve, reject) => {
      compilation.rebuildModule(oldModule, (err, rebuiltModule) => {
        if (err) {
          reject(err);
          return;
        }
        console.log(`Rebuilt ${rebuiltModule.identifier()}.`);
        resolve();
      });
    });
  });
});
```


Module.ts

### getLogger

以指定名称创建日志输出工具对象，以用于在插件中以统一的格式打印日志。

```ts
getLogger(name: string | (() => string)): Logger;
```

以下示例在 `processAssets` 中打印产物信息到 debug 日志中：

```js
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
  const logger = compilation.getLogger('MyPlugin');

  compilation.hooks.processAssets.tap('MyPlugin', () => {
    for (const asset of compilation.getAssets()) {
      logger.debug(`asset name: ${asset.name}`);
      logger.debug(`asset info: ${asset.info}`);
    }
  });
});
```


Logger.ts

### getCache

以指定名称获取缓存对象，以供插件在多次编译过程中共享数据。

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


Cache.ts

## Compilation 对象属性

### options

**类型：** `RspackOptionsNormalized`

获取此 Compilation 使用的完整配置，详见[配置 Rspack](https://rspack.rs/zh/config/index.md)。

### runtimeTemplate

**类型：** `RuntimeTemplate`

用于生成运行时代码的辅助方法，会根据 [`output.environment`](https://rspack.rs/zh/config/output.md#outputenvironment)
声明的目标环境能力来选择语法。相比手写代码片段，使用这些方法可以保证生成的代码在旧目标环境下依然合法。

```js
class MyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      const { runtimeTemplate } = compilation;

      // 支持箭头函数时为 `() => (globalThis)`，
      // 否则为 `function() { return globalThis; }`
      runtimeTemplate.returningFunction('globalThis');

      // 支持箭头函数时为 `(a) => {\n\tconsole.log(a);\n}`，
      // 否则为 `function(a) {\n\tconsole.log(a);\n}`
      runtimeTemplate.basicFunction('a', 'console.log(a);');
    });
  }
}
```


RuntimeTemplate.ts

### compiler

**类型：** `Compiler`

获取所属的[编译器对象](https://rspack.rs/zh/api/javascript-api/index.md)。


Compiler.ts

### hooks

获取 [Compilation 钩子](https://rspack.rs/zh/api/plugin-api/compilation-hooks.md)。

### hash/fullHash

**类型：** `Readonly<string | null>`

表示当前整个 compilation 的哈希值。Rspack 根据各个 chunk 的哈希、内容哈希以及内部重建状态计算该值。

在 Rspack 中，`hash` 和 `fullHash` 是只读的别名属性，返回值相同：

- `null`：尚未计算 compilation 的哈希，例如执行 `thisCompilation` 钩子时。
- `string`：compilation 的哈希已生成。可以在哈希计算之后执行的钩子中读取，例如 [processAssets](https://rspack.rs/zh/api/plugin-api/compilation-hooks.md#processassets) 或 [afterSeal](https://rspack.rs/zh/api/plugin-api/compilation-hooks.md#afterseal)。

哈希在资源处理阶段之前计算。在 `processAssets` 中更新资源不会自动重新计算该值。

```js
compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.processAssets.tap('MyPlugin', () => {
    console.log('Compilation hash:', compilation.hash);
    // compilation.fullHash 的值相同。
  });
});
```

### assets

**类型：** `Record<string, Source>`

获取产物映射表。


Source.ts

### chunkGroups

**类型：** `ReadonlyArray<ChunkGroup>`

获取 Chunk Group 对象列表，结构如下：


ChunkGroup.ts

### entrypoints

**类型：** `ReadonlyMap<string, Entrypoint>`

获取 Entry 对象映射表，其为作为入口的特殊的 Chunk Group，会额外包含一个 Runtime Chunk。


Entrypoint.ts

### namedChunkGroups

**类型：** `ReadonlyMap<string, Readonly<ChunkGroup>>`

获取名称与 Chunk Group 对象映射表。


ChunkGroup.ts

### modules

**类型：** `ReadonlySet<Module>`

获取所有模块，其结构如下：


Module.ts

### builtModules

**类型：** `ReadonlySet<Module>`

获取未缓存被构建的模块，其结构如下：


Module.ts

### chunks

**类型：** `ReadonlySet<Chunk>`

获取所有 Chunk，其结构如下：


Chunk.ts

### namedChunks

**类型：** `ReadonlyMap<string, Readonly<Chunk>>`

获取名称与 Chunk 对象的映射表。


Chunk.ts

### fileDependencies

**类型：** `FileSystemDependencies`

获取此 Compilation 对资源文件的依赖信息，其结构如下：


FileSystemDependencies.ts

### contextDependencies

**类型：** `FileSystemDependencies`

获取此 Compilation 对目录的依赖信息。


FileSystemDependencies.ts

### missingDependencies

**类型：** `FileSystemDependencies`

获取此 Compilation 对缺失文件的依赖信息。


FileSystemDependencies.ts

### buildDependencies

**类型：** `FileSystemDependencies`

获取此 Compilation 对构建文件的依赖信息。


FileSystemDependencies.ts

### errors

**类型：** `RspackError[]`

获取构建期间产生的错误对象列表，其结构如下：


RspackError.ts

### warnings

**类型：** `RspackError[]`

获取构建期间产生的警告对象列表。


RspackError.ts


本页改编自 [webpack 文档](https://webpack.docschina.org/api/compilation-object/)，遵循 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)，且已作修改。

