From c37b0bfd78f992bfcfba5c47ab7bdc0201c4ac17 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 10:44:01 -0500 Subject: [PATCH 1/9] docs(configuration): add defineConfig helper usage examples --- .../configuration/configuration-languages.mdx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/content/configuration/configuration-languages.mdx b/src/content/configuration/configuration-languages.mdx index 9f0a1055bd0c..c15717a99ec7 100644 --- a/src/content/configuration/configuration-languages.mdx +++ b/src/content/configuration/configuration-languages.mdx @@ -19,6 +19,33 @@ contributors: Webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found in the [node-interpret](https://github.com/gulpjs/interpret) package. Using [node-interpret](https://github.com/gulpjs/interpret), webpack can handle many different types of configuration files. +## defineConfig + + + +`defineConfig` is a helper exported from `webpack` that gives editors type-checking and autocomplete for your configuration without any extra type annotations. It is an identity function (a no-op at runtime that simply returns the config you pass in), so it works in plain JavaScript configs too. + +**webpack.config.js** + +```js +const { defineConfig } = require("webpack"); + +module.exports = defineConfig({ + mode: "none", +}); +``` + +It accepts every shape webpack-cli can load: a single configuration object, an array of configurations (multi-compiler), a function returning either of those, an array of such functions, or a `Promise` resolving to any of them. + +```js +const { defineConfig } = require("webpack"); + +module.exports = defineConfig((env, argv) => ({ + mode: argv.mode ?? "development", + // ... +})); +``` + ## TypeScript To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: From 2873c29defe74e9cc9011da72530fbcc458883ce Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 10:48:43 -0500 Subject: [PATCH 2/9] docs(target): add 'universal' target option with usage details --- src/content/configuration/target.mdx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/content/configuration/target.mdx b/src/content/configuration/target.mdx index a27c8d49b4f0..8df5208af93b 100644 --- a/src/content/configuration/target.mdx +++ b/src/content/configuration/target.mdx @@ -40,6 +40,7 @@ The following string values are supported via [`WebpackOptionsApply`](https://gi | `nwjs[[X].Y]` | The same as `node-webkit` | | `web` | Compile for usage in a browser-like environment **(default)** | | `webworker` | Compile as WebWorker | +| `universal` | Compile a single bundle that adapts at runtime to browser, web worker, Node.js, Electron and NW.js. Always outputs ECMAScript modules. Available since webpack 5.108.0. | | `esX` | Compile for specified ECMAScript version. Examples: es5, es2020. | | `browserslist` | Infer a platform and the ES-features from a browserslist-config **(default if browserslist config is available)** | @@ -73,6 +74,27 @@ Supported browserslist values: - `browserslist:/path/to/config` - explicitly specify browserslist config - `browserslist:/path/to/config:modern` - explicitly specify browserslist config and an environment +#### universal + + + +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. + +**webpack.config.js** + +```js +export default { + // ... + target: "universal", +}; +``` + +Notes for universal builds: + +- `new Worker(new URL(...))` resolves the `Worker` constructor from `worker_threads` in Node and from the global `Worker` on the web. +- `commonjs` and `node-commonjs` externals are supported in the ESM output (loaded via `createRequire` from `process.getBuiltinModule`), and `global` externals use `globalThis` as the global object. +- CSS runs in Node for server-side rendering: styles from `style` injection and `link`-loaded chunks are collected into `globalThis["__webpack_css__" + output.uniqueName]` for an SSR host to read. + ### [string] When multiple targets are passed, then common subset of features will be used: From 1bfd390d260148bc483d4335bff94da5667d0b46 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 11:11:39 -0500 Subject: [PATCH 3/9] docs(output): add new capability flags and options for webpack 5.108.0 --- src/content/configuration/output.mdx | 70 ++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/src/content/configuration/output.mdx b/src/content/configuration/output.mdx index 29b97b485654..4dfaf4146da2 100644 --- a/src/content/configuration/output.mdx +++ b/src/content/configuration/output.mdx @@ -496,12 +496,16 @@ export default { asyncFunction: true, // The environment supports BigInt as literal (123n). bigIntLiteral: false, - // The environment supports const and let for variable declarations. + // The environment supports const for variable declarations. const: true, + // The environment supports let for variable declarations. + let: true, // The environment supports destructuring ('{ a, b } = obj'). destructuring: true, // The environment supports 'document' variable. document: true, + // The environment supports 'Object.hasOwn'. + hasOwn: true, // The environment supports an async import() function to import EcmaScript modules. dynamicImport: false, // The environment supports an async import() when creating a worker, only for web targets at the moment. @@ -514,11 +518,17 @@ export default { module: false, // The environment supports object method shorthand ('{ module() {} }'). methodShorthand: true, + // The environment supports `process.getBuiltinModule()` to synchronously load Node.js core modules. + nodeBuiltinModuleGetter: false, // Determines if the node: prefix is generated for core module imports in environments that support it. // This is only applicable to Webpack runtime code. nodePrefixForCoreModules: false, // The environment supports optional chaining ('obj?.a' or 'obj?.()'). optionalChaining: true, + // The environment supports spread and rest in array/object literals and calls ('{ ...obj }', 'fn(...args)'). + spread: true, + // The environment supports 'Symbol' (and well-known symbols like 'Symbol.toStringTag'). + symbol: true, // The environment supports template literals. templateLiteral: true, // The environment supports `import.meta.dirname` and `import.meta.filename`. @@ -528,6 +538,10 @@ export default { }; ``` +These capability flags are normally inferred from your [`target`](/configuration/target/); you only set them manually to override that detection. When a flag is enabled, webpack emits the corresponding modern syntax in its generated runtime code and otherwise falls back to the equivalent legacy output. + +T> `let`, `spread`, `hasOwn`, `symbol`, and `nodeBuiltinModuleGetter` were added in webpack 5.108.0. `let` falls back to the value of `const` when the target does not report it separately, `spread` and `symbol` are optimistic (enabled unless the target reports a lack of support), and `hasOwn` is enabled only when the target explicitly reports `Object.hasOwn` support. `nodeBuiltinModuleGetter` reflects support for `process.getBuiltinModule()` and is used by universal builds to load Node.js core modules without breaking the browser. + ## output.filename `string` `function (pathData, assetInfo) => string` @@ -627,10 +641,11 @@ The following substitutions are available in template strings (via webpack's int Substitutions available on Compilation-level: -| Template | Description | -| ---------- | ---------------------------- | -| [fullhash] | The full hash of compilation | -| [hash] | Same, but deprecated | +| Template | Description | +| ------------ | -------------------------------------------------------------------------------------- | +| [fullhash] | The full hash of compilation | +| [hash] | Same, but deprecated | +| [uniqueName] | The value of [`output.uniqueName`](#outputuniquename) (alias `[uniquename]`, 5.108.0+) | Substitutions available on Chunk-level: @@ -2410,6 +2425,27 @@ export default { }; ``` +## output.strictModuleResolution + +Emit a runtime check that throws a `MODULE_NOT_FOUND` error when a required module id is missing from the bundle. + +- Type: `boolean` +- Available: 5.108.0+ + +It defaults to `true` in [`development`](/configuration/mode/#mode-development) mode and `false` in [`production`](/configuration/mode/#mode-production) mode. Set it explicitly to re-enable the guard in production (useful for debugging) or to drop it in development. + +```js +export default { + mode: "production", + output: { + // re-enable the MODULE_NOT_FOUND runtime guard in production + strictModuleResolution: true, + }, +}; +``` + +T> Before 5.108.0 this runtime guard was tied to [`output.pathinfo`](#outputpathinfo). It is now controlled by its own dedicated option. + ## output.strictModuleExceptionHandling W> Deprecated, use @@ -2567,6 +2603,30 @@ export default { }; ``` +## output.workerChunkFilename + +`string` `function (pathData, assetInfo) => string` + +- Available: 5.108.0+ + +This option determines the name of non-initial worker chunk files. It accepts the same string templates and function form as [`output.chunkFilename`](#outputchunkfilename), and defaults to the value of `output.chunkFilename`. Setting it lets you give worker chunks their own naming scheme independently of regular chunks. + +You must not specify an absolute path here, but the path may contain folders separated by `/`. The specified path is joined with the value of the [`output.path`](#outputpath) option to determine the location on disk. + +**webpack.config.js** + +```js +export default { + // ... + output: { + chunkFilename: "[name].chunk.js", + workerChunkFilename: "workers/[name].[contenthash].worker.js", + }, +}; +``` + +T> `WorkerPlugin` marks the entries it creates from `new Worker(new URL(...))` so their output files use `workerChunkFilename`. See also the entry-level [`worker`](/configuration/entry-context/#entry-descriptor) flag. A `filename` set for a specific worker entry still takes precedence over this option. + ## output.workerChunkLoading `string: 'require' | 'import-scripts' | 'async-node' | 'import' | 'universal'` `boolean: false` From ae3782f1eb1d992e8517142d44c55150c351e94e Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 11:23:23 -0500 Subject: [PATCH 4/9] docs(optimization): add inlineExports option with detailed explanation and usage example --- src/content/configuration/optimization.mdx | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/content/configuration/optimization.mdx b/src/content/configuration/optimization.mdx index 409237a60b50..ae1cb37bed19 100644 --- a/src/content/configuration/optimization.mdx +++ b/src/content/configuration/optimization.mdx @@ -245,6 +245,60 @@ export default { }; ``` +## optimization.inlineExports + +`boolean` + + + +Inline ESM exports that bind to small primitive constants (a `null`, `undefined`, `boolean`, `number` or `string` of at most 6 bytes) at every import site, replacing the imported binding with the literal value. Once every import is replaced, the import dependency becomes inactive, the export turns unused, and dead-code elimination can drop the export and, if the module is side-effect free, the whole module. + +The default value of `optimization.inlineExports` depends on the [`mode`](/configuration/mode/): + +| Mode | Default | +| --------------- | ------- | +| `"production"` | `true` | +| `"development"` | `false` | +| `"none"` | `false` | + +**webpack.config.js** + +```js +export default { + // ... + optimization: { + inlineExports: true, + }, +}; +``` + +This happens in two steps. Given these modules: + +```js +// flags.js +export const DEBUG = false; // a ≤6-byte boolean +``` + +```js +// app.js +import { DEBUG } from "./flags.js"; + +if (DEBUG) doSomething(); +``` + +First, every reference to the imported binding is replaced with its literal value (inlining): + +{/* eslint-skip */} + +```js +// app.js (conceptual result) +if (false) doSomething(); +``` + +Then, because no import references `DEBUG` anymore, the `export const DEBUG` is left unused and dead-code elimination drops it. If `flags.js` has no side effects, the whole module is removed too. The consuming code can additionally collapse the now-constant branch (`if (false) ...`). + +T> Only small primitive constants are inlined: a `null`, `undefined`, `boolean`, `number` or `string` of at most 6 bytes. Objects, arrays and longer strings are left as regular exports. + ## optimization.mangleExports `boolean` `string: 'deterministic' | 'size'` From e7599ba621a1d5bd30153381c4c4897157c4194a Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 11:28:03 -0500 Subject: [PATCH 5/9] docs(entry): add worker flag description for entry points in webpack 5.108.0 --- src/content/configuration/entry-context.mdx | 3 +++ src/content/configuration/output.mdx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/content/configuration/entry-context.mdx b/src/content/configuration/entry-context.mdx index 283928a1f688..5066301fd63e 100644 --- a/src/content/configuration/entry-context.mdx +++ b/src/content/configuration/entry-context.mdx @@ -88,6 +88,7 @@ export default { chunkLoading: "jsonp", asyncChunks: true, // Create async chunks that are loaded on demand. layer: "name of layer", // set the layer for an entry point + worker: true, // mark as a worker entry, available since webpack 5.108.0 }, }, }; @@ -95,6 +96,8 @@ export default { Descriptor syntax might be used to pass additional options to an entry point. +T> The `worker` flag (added in webpack 5.108.0) marks an entry as a worker so its output file uses [`output.workerChunkFilename`](/configuration/output/#outputworkerchunkfilename) instead of the regular chunk filename. webpack sets it automatically for entries it creates from `new Worker(new URL(...))`, so you rarely set it by hand. + ### Output filename By default, the output filename for the entry chunk is extracted from [`output.filename`](/configuration/output/#outputfilename) but you can specify a custom output filename for a specific entry: diff --git a/src/content/configuration/output.mdx b/src/content/configuration/output.mdx index 4dfaf4146da2..19f7550ac275 100644 --- a/src/content/configuration/output.mdx +++ b/src/content/configuration/output.mdx @@ -2625,7 +2625,7 @@ export default { }; ``` -T> `WorkerPlugin` marks the entries it creates from `new Worker(new URL(...))` so their output files use `workerChunkFilename`. See also the entry-level [`worker`](/configuration/entry-context/#entry-descriptor) flag. A `filename` set for a specific worker entry still takes precedence over this option. +T> Entries that webpack creates automatically from `new Worker(new URL(...))` are marked as workers, so their output files use `workerChunkFilename`. See also the entry-level [`worker`](/configuration/entry-context/#entry-descriptor) flag. A `filename` set for a specific worker entry still takes precedence over this option. ## output.workerChunkLoading From 30b4223177547bdfb540164f7571ce8652d573f4 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 11:31:20 -0500 Subject: [PATCH 6/9] docs(tree-shaking): update annotation behavior and side-effect-free configuration details for webpack 5.108.0 --- src/content/guides/tree-shaking.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content/guides/tree-shaking.mdx b/src/content/guides/tree-shaking.mdx index 3f5f3c83423c..7e8af93c3edc 100644 --- a/src/content/guides/tree-shaking.mdx +++ b/src/content/guides/tree-shaking.mdx @@ -544,7 +544,9 @@ import { createLogger } from "./utils"; const unused = createLogger("debug"); ``` -W> The annotation currently only takes effect within the module where it is declared. Cross-module propagation is planned for a future release. +T> Since webpack 5.108.0 the annotation propagates across module boundaries, so an unused call in an importing module is tree-shaken too. (Before 5.108.0 it only took effect within the module where it was declared.) + +T> If you can't edit the source to add the annotation (for example, a function coming from a dependency), you can mark names as side-effect-free from your config with [`module.parser.javascript.pureFunctions`](/configuration/module/#moduleparserjavascriptpurefunctions) (5.108.0+). ## Minify the Output From e7f589bd17c6c57505f160b2f08e217a5a5f78e9 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 18 Jun 2026 11:47:48 -0500 Subject: [PATCH 7/9] docs(module): add new parser options for CSS and HTML modules in webpack 5.108.0 --- src/content/configuration/module.mdx | 161 +++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/src/content/configuration/module.mdx b/src/content/configuration/module.mdx index d807124696e9..e8f245178347 100644 --- a/src/content/configuration/module.mdx +++ b/src/content/configuration/module.mdx @@ -293,6 +293,9 @@ export default { requireEnsure: true, // Set the module to `'strict'` or `'non-strict'` mode. This can affect the module's behavior, as some behaviors differ between strict and non-strict modes. overrideStrict: "non-strict", + // Mark top-level function names as side-effect-free for tree shaking, available since webpack 5.108.0 + // type: string[] + pureFunctions: ["myPureFn"], }, "javascript/auto": { // ditto @@ -318,6 +321,9 @@ export default { // Configure how CSS content is exported // type: string exportType: "link", + // Select the top-level CSS production to parse, available since webpack 5.108.0 + // type: 'stylesheet' | 'block-contents' + as: "stylesheet", }, "css/auto": { // ditto @@ -328,6 +334,16 @@ export default { "css/module": { // ditto }, + html: { + // Parser options for html modules, requires `experiments.html`, available since webpack 5.108.0 + + // Disable or customize URL-attribute extraction + // type: boolean | Array<'...' | { tag?: string, attribute: string, type: string, filter?: Function }> + sources: true, + // Transform the HTML source before it is parsed + // type: (source: string, context: HtmlTemplateContext) => string + template: undefined, + }, // others… }, }, @@ -691,6 +707,34 @@ Possible values: `'link' | 'text' | 'css-style-sheet' - `text` - store CSS in JS file and return using default export. - `css-style-sheet` - the default export is a constructable stylesheet (i.e. CSSStyleSheet). Useful for custom elements and shadow DOM. +### module.parser.css.as + +Select the top-level CSS production to parse. + +- Type: `'stylesheet' | 'block-contents'` +- Available: 5.108.0+ +- Example: + + ```js + export default { + experiments: { css: true }, + module: { + parser: { + css: { + as: "block-contents", + }, + }, + }, + }; + ``` + +Possible values: + +- `stylesheet` (default) - parse the source as a full stylesheet. +- `block-contents` - parse the source as a CSS block's contents (a declaration list), i.e. the inside of an HTML `style="..."` attribute. + +T> This option exists so webpack can route an HTML inline `style="..."` attribute through the CSS pipeline (resolving `url()`, `image-set()` and `@import` relative to the HTML file). For the common HTML `style=` case you don't need to set it manually. Just enable `experiments: { html: true, css: true }` and `url()` inside `style` attributes resolves automatically. + ### module.parser.javascript Configure options for JavaScript parser. @@ -977,6 +1021,31 @@ Set the module to `'strict'` or `'non-strict'` mode. This can affect the module' }; ``` +#### module.parser.javascript.pureFunctions + +Mark the listed top-level function names as side-effect-free, so calls to them whose results are unused can be tree-shaken. This is the explicit-config counterpart of the [`/*#__NO_SIDE_EFFECTS__*/`](/guides/tree-shaking/#mark-a-function-declaration-as-side-effect-free) annotation: instead of annotating the source, you list the names. Use `"default"` to target a default-exported function. + +- Type: `string[]` +- Available: 5.108.0+ +- Example: + + ```js + export default { + module: { + rules: [ + { + test: /pure-source\.js$/, + parser: { + pureFunctions: ["createSelector", "styled", "default"], + }, + }, + ], + }, + }; + ``` + +T> Best applied per-rule with a `test` so the names are only marked side-effect-free in the intended module. A global form (`module.parser.javascript.pureFunctions`) is also supported. + #### module.parser.javascript.reexportExportsPresence Specifies the behavior of invalid export names in `\"export ... from ...\"`. This might be useful to disable during the migration from `\"export ... from ...\"` to `\"export type ... from ...\"` when reexporting types in TypeScript. @@ -1172,6 +1241,98 @@ export default { }; ``` +### module.parser.html + + + +Configure options for the HTML parser. These options require the [`experiments.html`](/configuration/experiments/#experimentshtml) flag to be enabled. + +```js +export default { + experiments: { html: true }, + module: { + parser: { + html: { + // ... + sources: true, + }, + }, + }, +}; +``` + +#### module.parser.html.sources + +Controls extraction of URL-like attribute values (``, ``, `