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

# ESM 产物

Rspack 支持使用 ESM 格式输出进行打包。构建应用时，Rspack 默认会生成基于 IIFE 格式代码的打包输出，而不是标准的 CommonJS 或 ESM 格式，你可以通过配置 [output.module](/zh/config/output.md#outputmodule) 来生成 ESM 格式的产物。下面的章节介绍了如何 [构建应用的 ESM 格式产物](#构建应用的-esm-格式产物) 及 [构建库的 ESM 格式产物](#构建库的-esm-格式产物) 并在最后列出了与 ESM 产物相关的 [配置清单](#配置清单)。

## 构建应用的 ESM 格式产物

在构建应用时，Rspack 默认会生成依赖 Rspack runtime 的产物。如果你需要生成 ESM 格式的产物，可以在 `rspack.config.mjs` 中进行如下配置：

```js title="rspack.config.mjs"
export default {
  output: {
    module: true,
    chunkFormat: 'module',
    chunkLoading: 'import',
    workerChunkLoading: 'import',
  },
};
```

你可以在 rspack-examples 中查看 [React 应用构建到 ESM 产物](https://github.com/rstackjs/rstack-examples/tree/main/rspack/react-refresh-esm) 及 [React ESM SSR](https://github.com/rstackjs/rstack-examples/tree/main/rspack/react-ssr-esm) 的示例。

## 构建库的 ESM 格式产物

推荐使用 [Rslib](https://rslib.rs) 来构建库产物，Rslib 底层基于 Rspack 实现，能够构建 ES Module、CommonJS 和 UMD 等多种格式的产物。Rslib 提供了更高层次的 API，简化了库的构建过程。相比直接使用 Rspack，使用 Rslib 进行库的构建会更加方便和高效。

如果你需要直接使用 Rspack 构建库（npm library）的 ESM 格式产物，推荐优先使用 `modern-module`：

```js title="rspack.config.mjs"
export default {
  output: {
    library: {
      type: 'modern-module',
    },
  },
  optimization: {
    avoidEntryIife: true,
    minimize: false,
  },
};
```

与应用场景的 `output.module: true` 不同，`modern-module` 会切换到一条专门面向库的 ESM 渲染路径。它会自动启用 `output.module`，并切换到基于 `import` 的 chunk loading，因此通常不需要再手动指定 `chunkFormat: 'module'` 或 `chunkLoading: 'import'`。如果你的库还需要在 Worker 中以 ESM 方式加载 chunk，再额外配置 `workerChunkLoading: 'import'`。同时，也不要开启 `optimization.concatenateModules`，因为 `modern-module` 使用的是自己专门的链接与 scope hoist 逻辑。

你可以查看 [rspack-examples](https://github.com/rstackjs/rstack-examples/tree/main/rspack/library-esm) 中这个使用 ESM 库的例子。

进行 ESM 产物的打包还需要处理各种细节问题，这里不逐一列举。你可以参考 [Rslib 中对 ESM 格式的相关配置](https://github.com/web-infra-dev/rslib/blob/f727b18805767b99fb85ae67ebff959aa644536e/packages/core/src/config.ts)，或者直接使用 Rslib 开箱即用地进行库的构建。

## ESM 产物未来规划

相比早期版本，`modern-module` 现在已经覆盖了库场景中更关键的能力，包括 code splitting、自定义 splitChunks、[`output.library.preserveModules`](/zh/config/output.md#outputlibrarypreservemodules)，以及外部模块的 `export *` / `export * as` 等重新导出能力。

当前仍在持续完善的部分，更多集中在规范一致性和少量边界场景：

1. 更好的 ESM 应用产物与开发体验支持，包括 HMR 和 lazy compilation
2. namespace object 仍有少数行为与原生 ESM 不完全一致，例如 `null` prototype、冻结 / 不可扩展性，以及可枚举键顺序
3. 个别字符串导出名场景仍在补齐，例如以引号开头的字符串导出名会影响临时标识符生成
4. `preserveModules` 目前仅支持 `modern-module`，也不建议让同一个模块同时作为多个 entry 的输出根；这类配置当前会报错
5. `modern-module` 不能与其他 `library.type` 混用，因为它会接管 chunk 渲染、chunk loading 和 splitChunks 行为

换句话说，Rspack 的 ESM 工作重点已经从“能否输出 ESM”逐步转向“让库场景的 ESM 更接近原生语义，并覆盖更多边界情况”。

## 配置清单

下面列出了与 ESM 相关的主要配置选项及其说明，这些配置在构建应用和库时都会用到。

1. [output.module](/zh/config/output.md#outputmodule): 设置为 `true`，表示生成 ESM 格式的产物。开启此选项后，会对以下配置产生影响：
   1. 影响 [externalsType](/zh/config/externals.md#externalstype) 默认值：当 `output.module` 为 `true` 时，`externalsType` 默认为 `'module-import'`。出于兼容性考虑，`output.library.type: 'modern-module'` 当前仍保持这个默认值，除非显式配置 `externalsType: 'modern-module'`；下一个 major 版本中，`modern-module` externals 会成为 `modern-module` library 的默认值。
   2. 影响 [output.filename](/zh/config/output.md#outputfilename) 默认值：当 `output.module` 为 `true` 时，默认文件名为 `'[name].mjs'` 而不是 `'[name].js'`
   3. 间接影响 [output.chunkFilename](/zh/config/output.md#outputchunkfilename) 默认值：该值由 `output.filename` 推断，因此 ESM 输出下默认为 `'[name].mjs'`。自定义 `output.filename` 会影响此默认值；当其为函数时，`output.chunkFilename` 默认为 `'[id].js'`。
   4. 影响 [output.hotUpdateChunkFilename](/zh/config/output.md#outputhotupdatechunkfilename) 默认值：当 `output.module` 为 `true` 时，默认为 `'[id].[fullhash].hot-update.mjs'`
   5. 影响 [output.hotUpdateMainFilename](/zh/config/output.md#outputhotupdatemainfilename) 默认值：当 `output.module` 为 `true` 时，默认为 `'[runtime].[fullhash].hot-update.json.mjs'`
   6. 影响 [output.iife](/zh/config/output.md#outputiife) 默认值：当 `output.module` 为 `true` 时，`output.iife` 默认为 `false`
   7. 如果同时配置了 [`output.library`](/zh/config/output.md#outputlibrary) 且没有显式指定 [`output.library.type`](/zh/config/output.md#outputlibrarytype)，当 `output.module` 为 `true` 时，默认值为 `'modern-module'` 而不是 `'var'`
   8. 影响 [output.scriptType](/zh/config/output.md#outputscripttype) 默认值：当 `output.module` 为 `true` 时，默认为 `'module'`
   9. 影响 [output.environment.dynamicImport](/zh/config/output.md#outputenvironment) 默认值：当 `output.module` 为 `true` 时会被启用
   10. 影响 [output.environment.dynamicImportInWorker](/zh/config/output.md#outputenvironment) 默认值：当 `output.module` 为 `true` 时会被启用
   11. 影响 [output.environment.module](/zh/config/output.md#outputenvironment) 默认值：当 `output.module` 为 `true` 时会被启用
   12. 影响 Node.js 相关配置的默认值：在 Node.js 环境下，当 `output.module` 为 `true` 时，`__filename` 和 `__dirname` 默认为 `'node-module'`
2. [output.chunkFormat](/zh/config/output.md#outputchunkformat): 在构建应用的 ESM 产物时，通常设置为 `'module'`，表示使用 ESM 格式的 chunk。
3. [output.library.type](/zh/config/output.md#outputlibrarytype): 在构建库的 ESM 产物时，通常设置为 `'modern-module'`，表示使用 Rspack 专门的 ESM library 渲染路径。
4. [output.chunkLoading](/zh/config/output.md#outputchunkloading): 在构建应用的 ESM 产物时，通常设置为 `'import'`；对于 `modern-module`，Rspack 会自动切换到基于 `import` 的 chunk loading。
5. [output.workerChunkLoading](/zh/config/output.md#outputworkerchunkloading): 当你的应用或库还需要在 Worker 中以 ESM 方式加载 chunk 时，通常设置为 `'import'`。
6. [optimization.avoidEntryIife](/zh/config/optimization.md#optimizationavoidentryiife): 在某些情况下，Rspack 会将 ESM 产物的输出包裹在一个 IIFE 中，这会破坏 ESM 的模块化特性
7. [HtmlRspackPlugin.scriptLoading](/zh/plugins/html-rspack-plugin.md#scriptloading): 设置为 `'module'`，表示使用 ESM 的 `<script type="module">` 来加载 `.mjs` 模块。
