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

# ESM output

Rspack supports building with ESM format output. When building applications, Rspack generates IIFE-based bundled output by default instead of standard CommonJS or ESM format. You can configure [output.module](/config/output.md#outputmodule) to generate ESM format output. The following sections introduce how to [build application ESM output](#building-application-esm-output) and [build library ESM output](#building-library-esm-output), and finally list the [configuration checklist](#configuration-checklist) related to ESM output.

## Building application ESM output

When building applications, Rspack generates CommonJS-like format output by default. If you need to generate ESM format output, you can configure it in `rspack.config.mjs` as follows:

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

You can check out examples of [building React applications to ESM output](https://github.com/rstackjs/rstack-examples/tree/main/rspack/react-refresh-esm) and [React ESM SSR](https://github.com/rstackjs/rstack-examples/tree/main/rspack/react-ssr-esm) in rspack-examples.

## Building library ESM output

We recommend using [Rslib](https://rslib.rs) to build library output. Rslib is built on top of Rspack and can build multiple formats including ES Module, CommonJS, and UMD. Rslib provides higher-level APIs that simplify the library building process. Compared to using Rspack directly, using Rslib for library building is more convenient and efficient.

If you need to use Rspack directly to build ESM format output for libraries (npm library), `modern-module` is the recommended starting point:

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

Unlike application-oriented `output.module: true`, `modern-module` switches Rspack onto a dedicated ESM library rendering path. It automatically enables `output.module` and moves chunk loading to `import`, so you usually do not need to manually set `chunkFormat: 'module'` or `chunkLoading: 'import'`. If your library also needs ESM worker chunk loading, configure `workerChunkLoading: 'import'` explicitly. Also, do not enable `optimization.concatenateModules`, because `modern-module` uses its own linking and scope-hoisting pipeline.

You can check out this [rspack-examples](https://github.com/rstackjs/rstack-examples/tree/main/rspack/library-esm) ESM library example.

Building ESM output also requires handling various detailed issues, which are not listed exhaustively here. You can refer to the [ESM format related configurations in Rslib](https://github.com/web-infra-dev/rslib/blob/f727b18805767b99fb85ae67ebff959aa644536e/packages/core/src/config.ts), or use Rslib directly for out-of-the-box library building.

## Future plans for ESM output

Compared with earlier versions, `modern-module` now covers the more important library capabilities, including code splitting, custom splitChunks, [`output.library.preserveModules`](/config/output.md#outputlibrarypreservemodules), and external-module re-exports such as `export *` / `export * as`.

The remaining work is now more about spec alignment and edge cases than basic ESM availability:

1. Better application-oriented ESM output and development experience, including HMR and lazy compilation
2. Namespace objects still differ from native ESM in a few places, such as `null` prototype behavior, frozen / non-extensible semantics, and observable own-key ordering
3. Some string-export-name edge cases are still being completed, for example quoted names that affect temporary identifier generation
4. `preserveModules` currently only works with `modern-module`; using the same module as the output root of multiple entries is also discouraged, and currently errors
5. `modern-module` cannot be mixed with other `library.type` values in the same compilation, because it takes over chunk rendering, chunk loading, and splitChunks behavior

In other words, the focus has been shifting from "can Rspack emit ESM at all?" to "can Rspack make library ESM closer to native semantics across more edge cases?".

## Configuration checklist

Below are the main configuration options related to ESM and their descriptions, which are used when building both applications and libraries.

1. [output.module](/config/output.md#outputmodule): Set to `true` to generate ESM format output. When this option is enabled, it affects the following configurations:
   1. Affects [externalsType](/config/externals.md#externalstype) default value: When `output.module` is `true`, `externalsType` defaults to `'module-import'`. For compatibility, `output.library.type: 'modern-module'` currently keeps this default unless you explicitly configure `externalsType: 'modern-module'`; `modern-module` externals will become the default for `modern-module` libraries in the next major version.
   2. Affects [output.filename](/config/output.md#outputfilename) default value: When `output.module` is `true`, the default filename is `'[name].mjs'` instead of `'[name].js'`
   3. Affects [output.chunkFilename](/config/output.md#outputchunkfilename) default value indirectly: It is derived from `output.filename`, so the default is `'[name].mjs'` with ESM output. A custom `output.filename` can change this; when it is a function, `output.chunkFilename` defaults to `'[id].js'`.
   4. Affects [output.hotUpdateChunkFilename](/config/output.md#outputhotupdatechunkfilename) default value: When `output.module` is `true`, defaults to `'[id].[fullhash].hot-update.mjs'`
   5. Affects [output.hotUpdateMainFilename](/config/output.md#outputhotupdatemainfilename) default value: When `output.module` is `true`, defaults to `'[runtime].[fullhash].hot-update.json.mjs'`
   6. Affects [output.iife](/config/output.md#outputiife) default value: When `output.module` is `true`, `output.iife` defaults to `false`
   7. If [`output.library`](/config/output.md#outputlibrary) is also configured and [`output.library.type`](/config/output.md#outputlibrarytype) is not set explicitly, the default becomes `'modern-module'` instead of `'var'`
   8. Affects [output.scriptType](/config/output.md#outputscripttype) default value: When `output.module` is `true`, defaults to `'module'`
   9. Affects [output.environment.dynamicImport](/config/output.md#outputenvironment) default value: Enabled when `output.module` is `true`
   10. Affects [output.environment.dynamicImportInWorker](/config/output.md#outputenvironment) default value: Enabled when `output.module` is `true`
   11. Affects [output.environment.module](/config/output.md#outputenvironment) default value: Enabled when `output.module` is `true`
   12. Affects Node.js related configuration defaults: In Node.js environment, when `output.module` is `true`, `__filename` and `__dirname` default to `'node-module'`
2. [output.chunkFormat](/config/output.md#outputchunkformat): When building application ESM output, this is typically set to `'module'` to use ESM-format chunks.
3. [output.library.type](/config/output.md#outputlibrarytype): When building library ESM output, this is typically set to `'modern-module'` to use Rspack's dedicated ESM library rendering path.
4. [output.chunkLoading](/config/output.md#outputchunkloading): When building application ESM output, this is typically set to `'import'`; for `modern-module`, Rspack switches chunk loading to `import` automatically.
5. [output.workerChunkLoading](/config/output.md#outputworkerchunkloading): When your application or library also needs ESM worker chunk loading, this is typically set to `'import'`.
6. [optimization.avoidEntryIife](/config/optimization.md#optimizationavoidentryiife): In some cases, Rspack wraps ESM output in an IIFE, which breaks ESM's modular characteristics.
7. [HtmlRspackPlugin.scriptLoading](/plugins/html-rspack-plugin.md#scriptloading): Set to `'module'` to use ESM `<script type="module">` for loading `.mjs` modules.
