close

ESM 格式产物

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

构建应用的 ESM 格式产物

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

rspack.config.mjs
export default {
  output: {
    module: true,
    chunkFormat: 'module',
    chunkLoading: 'import',
    workerChunkLoading: 'import',
  },
};

你可以在 rspack-examples 中查看 React 应用构建到 ESM 产物React ESM SSR 的示例。

构建库的 ESM 格式产物

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

如果你需要直接使用 Rspack 构建库(npm library)的 ESM 格式产物,推荐优先使用 modern-module

rspack.config.mjs
export default {
  output: {
    library: {
      type: 'modern-module',
    },
  },
  externalsType: 'module-import',
  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 中这个使用 ESM 库的例子。

进行 ESM 产物的打包还需要处理各种细节问题,这里不逐一列举。你可以参考 Rslib 中对 ESM 格式的相关配置,或者直接使用 Rslib 开箱即用地进行库的构建。

ESM 产物未来规划

相比早期版本,modern-module 现在已经覆盖了库场景中更关键的能力,包括 code splitting、自定义 splitChunks、output.library.preserveModules,以及外部模块的 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: 设置为 true,表示生成 ESM 格式的产物。开启此选项后,会对以下配置产生影响:
    1. 影响 externalsType 默认值:当 output.moduletrue 时,externalsType 默认为 'module-import'
    2. 影响 output.filename 默认值:当 output.moduletrue 时,默认文件名为 '[name].mjs' 而不是 '[name].js'
    3. 影响 output.chunkFilename 默认值:当 output.moduletrue 时,chunk 文件名默认为 '[id].mjs' 而不是 '[id].js'
    4. 影响 output.hotUpdateChunkFilename 默认值:当 output.moduletrue 时,默认为 '[id].[fullhash].hot-update.mjs'
    5. 影响 output.hotUpdateMainFilename 默认值:当 output.moduletrue 时,默认为 '[runtime].[fullhash].hot-update.json.mjs'
    6. 影响 output.iife 默认值:当 output.moduletrue 时,output.iife 默认为 false
    7. 如果同时配置了 output.library 且没有显式指定 output.library.type,当 output.moduletrue 时,默认值为 'modern-module' 而不是 'var'
    8. 影响 output.scriptType 默认值:当 output.moduletrue 时,默认为 'module'
    9. 影响 output.environment.dynamicImport 默认值:当 output.moduletrue 时会被启用
    10. 影响 output.environment.dynamicImportInWorker 默认值:当 output.moduletrue 时会被启用
    11. 影响 output.environment.module 默认值:当 output.moduletrue 时会被启用
    12. 影响 Node.js 相关配置的默认值:在 Node.js 环境下,当 output.moduletrue 时,__filename__dirname 默认为 'node-module'
  2. output.chunkFormat: 在构建应用的 ESM 产物时,通常设置为 'module',表示使用 ESM 格式的 chunk。
  3. output.library.type: 在构建库的 ESM 产物时,通常设置为 'modern-module',表示使用 Rspack 专门的 ESM library 渲染路径。
  4. output.chunkLoading: 在构建应用的 ESM 产物时,通常设置为 'import';对于 modern-module,Rspack 会自动切换到基于 import 的 chunk loading。
  5. output.workerChunkLoading: 当你的应用或库还需要在 Worker 中以 ESM 方式加载 chunk 时,通常设置为 'import'
  6. optimization.avoidEntryIife: 在某些情况下,Rspack 会将 ESM 产物的输出包裹在一个 IIFE 中,这会破坏 ESM 的模块化特性
  7. HtmlWebpackPlugin.scriptLoading: 设置为 'module',表示使用 ESM 的 <script type="module"> 来加载 .mjs 模块。