Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/content/blog/2026-06-25-webpack-5-108.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.exports = {

[`target: "universal"`](/configuration/target/#universal) combines the `web`, `web worker`, `node`, `electron`, and `nwjs` platforms into one target and leaves each platform flag _neutral_ instead of locking the bundle to a single environment. Rather than compiling separate web and node bundles, you ship one bundle that figures out its surroundings at runtime and uses whatever the current platform provides.

A bundle that has to load equally well in a browser and in Node needs a portable module format, so universal builds always output ECMAScript modules: [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) defaults to `true`, synchronous `require` is turned off, and Node's built-in modules stay available (resolved at runtime through ESM). [`output.globalObject`](/configuration/output/#outputglobalobject) also defaults to `globalThis` so runtime code has one global to reach for on every platform.
A bundle that has to load equally well in a browser and in Node needs a portable module format, so universal builds always output ECMAScript modules: [`output.module`](/configuration/output/#outputmodule) defaults to `true`, synchronous `require` is turned off, and Node's built-in modules stay available (resolved at runtime through ESM). [`output.globalObject`](/configuration/output/#outputglobalobject) also defaults to `globalThis` so runtime code has one global to reach for on every platform.

To make a single bundle behave correctly everywhere, several pieces were made platform-aware and now branch on feature detection at runtime instead of being fixed at build time:

Expand Down
17 changes: 1 addition & 16 deletions src/content/configuration/experiments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ Available options:
- [`futureDefaults`](#experimentsfuturedefaults)
- [`html`](#experimentshtml)
- [`lazyCompilation`](#experimentslazycompilation)
- [`outputModule`](#experimentsoutputmodule)
- [`typescript`](#experimentstypescript)
- [`sourceImport`](#experimentssourceimport)
- `syncWebAssembly`: Support the old WebAssembly like in webpack 4.
- `outputModule`: Output ECMAScript module syntax wherever possible, removed since `5.111.0` — set [`output.module`](/configuration/output/#outputmodule) to `true` instead, it no longer needs an experiment.
- `layers`: Enable module and chunk layers, removed and works without additional options since `5.102.0`.
- `topLevelAwait`: Transforms a module into an `async` module when an `await` is used at the top level. Starting from webpack version `5.83.0` (however, in versions prior to that, you can enable it by setting `experiments.topLevelAwait` to `true`), this feature is enabled by default, removed and works without additional options since `5.102.0`.

Expand All @@ -45,7 +45,6 @@ export default {
asyncWebAssembly: true,
buildHttp: true,
lazyCompilation: true,
outputModule: true,
sourceImport: true,
syncWebAssembly: true,
topLevelAwait: true,
Expand Down Expand Up @@ -606,20 +605,6 @@ Compile entrypoints and dynamic `import`s only when they are in use. It can be u
};
```

### experiments.outputModule

`boolean`

Once enabled, webpack will output ECMAScript module syntax whenever possible. For instance, `import()` to load chunks, ESM exports to expose chunk data, among others.

```js
export default {
experiments: {
outputModule: true,
},
};
```

### experiments.typescript

<Badge text="5.107.0+" />
Expand Down
14 changes: 7 additions & 7 deletions src/content/configuration/externals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ jq(".my-element").animate(/* ... */);

Specify the default type of externals as `'module'`. Webpack will generate code like `import * as X from '...'` for externals used in a module.

Make sure to enable [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) first, otherwise webpack will throw errors.
Make sure to enable [`output.module`](/configuration/output/#outputmodule) first, otherwise webpack will throw errors.

#### Example

Expand All @@ -560,8 +560,8 @@ jq(".my-element").animate(/* ... */);

```js
export default {
experiments: {
outputModule: true,
output: {
module: true,
},
externalsType: "module",
externals: {
Expand Down Expand Up @@ -670,7 +670,7 @@ const src = await import.source("external-mod");

Specify the default type of externals as `'module-import'`. This combines [`'module'`](#externalstypemodule) and [`'import'`](#externalstypeimport). Webpack will automatically detect the type of import syntax, setting it to `'module'` for static imports and `'import'` for dynamic imports.

Ensure to enable [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) first if static imports exist, otherwise, webpack will throw errors.
Ensure to enable [`output.module`](/configuration/output/#outputmodule) first if static imports exist, otherwise, webpack will throw errors.

#### Example

Expand Down Expand Up @@ -752,8 +752,8 @@ jq(".my-element").animate(/* ... */);

```js
module.export = {
experiments: {
outputModule: true,
output: {
module: true,
},
externalsType: "node-commonjs",
externals: {
Expand Down Expand Up @@ -790,7 +790,7 @@ You can use `node-commonjs` to ensure that the prototype chain is preserved:
const { builtinModules } = require("node:module");

export default {
experiments: { outputModule: true },
output: { module: true },
externalsType: "node-commonjs",
externals: ({ request }, callback) => {
if (request.startsWith("node:") || builtinModules.includes(request)) {
Expand Down
25 changes: 8 additions & 17 deletions src/content/configuration/output.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1812,10 +1812,8 @@ These options will result in a bundle that comes with a complete header to ensur
```js
export default {
// …
experiments: {
outputModule: true,
},
output: {
module: true,
library: {
// do not specify a `name` here
type: "module",
Expand All @@ -1824,9 +1822,7 @@ export default {
};
```

Output ES Module.

However this feature is still experimental and not fully supported yet, so make sure to enable [experiments.outputModule](/configuration/experiments/) beforehand. In addition, you can track the development progress in [this thread](https://github.com/webpack/webpack/issues/2933#issuecomment-774253975).
Output ES Module. You can track the remaining development progress in [this thread](https://github.com/webpack/webpack/issues/2933#issuecomment-774253975).

##### type: 'modern-module'

Expand All @@ -1835,10 +1831,8 @@ However this feature is still experimental and not fully supported yet, so make
```js
export default {
// …
experiments: {
outputModule: true,
},
output: {
module: true,
library: {
// do not specify a `name` here
type: "modern-module",
Expand All @@ -1849,8 +1843,6 @@ export default {

This configuration generates tree-shakable output for ES Modules.

However this feature is still experimental and not fully supported yet, so make sure to enable [experiments.outputModule](/configuration/experiments/) beforehand.

##### type: 'commonjs2'

```js
Expand Down Expand Up @@ -2452,7 +2444,7 @@ These options will result in a bundle that comes with a complete header to ensur

W> Prefer to use [`output.library.type: 'module'`](#type-module).

Output ES Module. Make sure to enable [experiments.outputModule](/configuration/experiments/) beforehand.
Output ES Module. Make sure to enable [`output.module`](#outputmodule) beforehand.

Note that this feature is not fully supported yet, please track the progress in [this thread](https://github.com/webpack/webpack/issues/2933#issuecomment-774253975).

Expand Down Expand Up @@ -2677,7 +2669,7 @@ The dependencies for your library will be defined by the [`externals`](/configur

`boolean = false`

Output JavaScript files as module type. Disabled by default as it's an experimental feature.
Output JavaScript files as module type. It defaults to `true` for the [`universal`](/configuration/target/#universal), [`deno`](/configuration/target/#deno) and [`bun`](/configuration/target/#bun) targets, which only run ECMAScript modules, and to `false` everywhere else.

When enabled, webpack will set [`output.iife`](#outputiife) to `false`, [`output.scriptType`](#outputscripttype) to `'module'` and `minimizerOptions.module` to `true` internally.

Expand All @@ -2686,16 +2678,15 @@ If you're using webpack to compile a library to be consumed by others, make sure
```js
export default {
// ...
experiments: {
outputModule: true,
},
output: {
module: true,
},
};
```

W> `output.module` is an experimental feature and can only be enabled by setting [`experiments.outputModule`](/configuration/experiments/#experiments) to `true`. [One of the known problems](https://github.com/webpack/webpack/issues/11277#issuecomment-992565287) is that such a library can't be consumed by webpack4-based (and possibly other too) applications.
T> Until webpack `5.111.0` this option also required [`experiments.outputModule`](/configuration/experiments/); that experiment has been removed and `output.module` now works on its own.

W> [One of the known problems](https://github.com/webpack/webpack/issues/11277#issuecomment-992565287) is that such a library can't be consumed by webpack4-based (and possibly other too) applications.

## output.path

Expand Down
1 change: 0 additions & 1 deletion src/content/configuration/performance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ What each reason means, and what lifts it:
```js
export default {
// ...
experiments: { outputModule: true },
output: { module: true },
performance: {
hints: "warning",
Expand Down
6 changes: 3 additions & 3 deletions src/content/configuration/target.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Supported browserslist values:

<Badge text="5.108.0+" />

A single preset that combines the `web`, `web worker`, `node`, `electron` and `nwjs` platforms, leaving each platform flag neutral so the bundle adapts at runtime instead of being locked to one environment. It is a convenient replacement for hand-writing `target: ["web", "node"]`, and it always outputs ECMAScript modules. [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) defaults to `true` for this target.
A single preset that combines the `web`, `web worker`, `node`, `electron` and `nwjs` platforms, leaving each platform flag neutral so the bundle adapts at runtime instead of being locked to one environment. It is a convenient replacement for hand-writing `target: ["web", "node"]`, and it always outputs ECMAScript modules. [`output.module`](/configuration/output/#outputmodule) defaults to `true` for this target.

**webpack.config.js**

Expand All @@ -101,7 +101,7 @@ Notes for universal builds:

<Badge text="5.108.0+" />

Compile for [Bun](https://bun.sh/). The bundle is emitted as ECMAScript modules ([`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) defaults to `true`), and Bun's own `bun:*` modules together with the Node.js built-in modules Bun provides are externalized instead of being bundled.
Compile for [Bun](https://bun.sh/). The bundle is emitted as ECMAScript modules ([`output.module`](/configuration/output/#outputmodule) defaults to `true`), and Bun's own `bun:*` modules together with the Node.js built-in modules Bun provides are externalized instead of being bundled.

**webpack.config.js**

Expand All @@ -116,7 +116,7 @@ export default {

<Badge text="5.108.0+" />

Compile for [Deno](https://deno.com/). The bundle is emitted as ECMAScript modules ([`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) defaults to `true`). Node.js built-ins are resolved through the `node:` specifier Deno requires, and Deno's own import protocols (`npm:`, `jsr:`, `node:` and `http(s)://` URLs) are kept external so the runtime loads them. A version may be specified, for example `deno2` or `deno1.40`.
Compile for [Deno](https://deno.com/). The bundle is emitted as ECMAScript modules ([`output.module`](/configuration/output/#outputmodule) defaults to `true`). Node.js built-ins are resolved through the `node:` specifier Deno requires, and Deno's own import protocols (`npm:`, `jsr:`, `node:` and `http(s)://` URLs) are kept external so the runtime loads them. A version may be specified, for example `deno2` or `deno1.40`.

**webpack.config.js**

Expand Down
7 changes: 2 additions & 5 deletions src/content/guides/modern-web-platform.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Splitting alone does not change **browser** rules: the tag name must still be re

### Approach

Enable [ES module output](/configuration/output/#outputmodule) (`experiments.outputModule` and `output.module`), set [`externalsType: "module"`](/configuration/externals/#externalstypemodule) for static imports, and list each bare specifier in `externals` with the same string the browser will resolve via the import map.
Enable [ES module output](/configuration/output/#outputmodule) (`output.module`), set [`externalsType: "module"`](/configuration/externals/#externalstypemodule) for static imports, and list each bare specifier in `externals` with the same string the browser will resolve via the import map.

**webpack.config.js**

Expand All @@ -83,9 +83,6 @@ const __dirname = path.dirname(__filename);

export default {
mode: "production",
experiments: {
outputModule: true,
},
entry: "./src/index.js",
externalsType: "module",
externals: {
Expand Down Expand Up @@ -131,7 +128,7 @@ The key `"lodash-es"` must match both the **`externals` key** and the **specifie
<script type="module" src="/dist/main.mjs"></script>
```

W> [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) and [`output.module`](/configuration/output/#outputmodule) are still experimental. Check the latest [webpack release notes](https://github.com/webpack/webpack/releases) before relying on them in production.
W> Check the latest [webpack release notes](https://github.com/webpack/webpack/releases) for the current state of [`output.module`](/configuration/output/#outputmodule) before relying on it in production.

### Limitations and future work

Expand Down
2 changes: 1 addition & 1 deletion src/content/guides/native-html.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@ A `UrlHintRule` — used by `output.resourceHints.urlHints` and by every parser'

```js
export default {
experiments: { html: true, outputModule: true },
experiments: { html: true },
output: {
module: true,
resourceHints: {
Expand Down
Loading