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
27 changes: 27 additions & 0 deletions src/content/configuration/configuration-languages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Badge text="5.108.0+" />

`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:
Expand Down
3 changes: 3 additions & 0 deletions src/content/configuration/entry-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,16 @@ 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
},
},
};
```

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:
Expand Down
29 changes: 28 additions & 1 deletion src/content/configuration/experiments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,9 @@ import page from "./page.html";
document.documentElement.innerHTML = page;
```

W> **This feature is experimental and partial.** Webpack 5.107 only implements the `html-loader` side: importing an HTML file from JS runs its tag references through the webpack pipeline. **HTML entry points** (using a `.html` file directly as `entry`, the `html-webpack-plugin` part) are **not supported yet** and are planned for the next minor release. The full story is tracked in issue [#536](https://github.com/webpack/webpack/issues/536).
W> **This feature is experimental and partial.** Webpack 5.107 implemented the `html-loader` role: importing an HTML file from JS runs its tag references through the webpack pipeline. Since 5.108 a `.html` file can also be used as an entry, and the default `./src` entry resolves to `index.html` when this experiment is enabled (see [HTML as the default entry](#html-as-the-default-entry) below). Full parity with `html-webpack-plugin` is still in progress; the overall effort is tracked in issue [#536](https://github.com/webpack/webpack/issues/536).

T> The HTML parser can be tuned via [`module.parser.html`](/configuration/module/#moduleparserhtml): use [`sources`](/configuration/module/#moduleparserhtmlsources) to disable or customize URL-attribute extraction, and [`template`](/configuration/module/#moduleparserhtmltemplate) to transform the HTML source before parsing.

#### Inline `<style>` tags

Expand Down Expand Up @@ -488,6 +490,31 @@ A few behaviors to keep in mind:

Placing an HTML `<!-- webpackIgnore: true -->` comment immediately before a tag tells webpack to skip URL resolution for that tag's `src`, `href`, `srcset`, and similar attributes. See the full description under [magic comments](/api/module-methods/#webpackignore).

#### HTML as the default entry

<Badge text="5.108.0+" />

When `experiments.html` is enabled, `.html` is added to the default `resolve.extensions` ahead of the JavaScript extensions, so a directory entry like `entry: "./src"` resolves `./src/index.html` even when `./src/index.js` also exists. This makes the build HTML-first, similar to Vite or Parcel.

```js
export default {
experiments: { html: true },
entry: "./src", // resolves to ./src/index.html
};
```

When [`experiments.css`](#experimentscss) is enabled, `.css` is likewise appended to the default extensions, so the default entry can fall back to `./src/index.css` when no HTML or JS match is found. These extensions are only added when the respective experiment is on, so default builds are unchanged.

#### Hot Module Replacement

<Badge text="5.108.0+" />

HTML modules support [Hot Module Replacement](/concepts/hot-module-replacement/). No extra configuration is needed. It activates automatically when HMR is enabled (for example via [`devServer.hot`](/configuration/dev-server/#devserverhot)).

For a page extracted to a real `.html` file, each hot update patches `document.body.innerHTML` and `document.title` in place instead of triggering a full reload. Changes to `<head>` beyond the `<title>` (a new `<meta>`, a swapped `<link rel="icon">`, …) cannot be safely DOM-patched, so the shim falls back to a full page reload.

T> [Module concatenation](/configuration/optimization/#optimizationconcatenatemodules) is disabled for HTML modules while HMR is active, because each module needs its own `module.hot` scope to self-accept updates.

### experiments.lazyCompilation

Compile entrypoints and dynamic `import`s only when they are in use. It can be used for either Web or Node.js.
Expand Down
161 changes: 161 additions & 0 deletions src/content/configuration/module.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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…
},
},
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -1172,6 +1241,98 @@ export default {
};
```

### module.parser.html

<Badge text="5.108.0+" />

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 (`<img src>`, `<link href>`, `<script src>`, …) as webpack dependencies.

- Type: `boolean | Array<'...' | { tag?: string, attribute: string, type: string, filter?: (attributes: Map<string, string>) => boolean }>`
- Available: 5.108.0+

Possible values:

- `true` (default) - extract URL-like attributes using the built-in source list.
- `false` - disable extraction entirely. URL-like attributes are left untouched and `<script src>`, `<link rel="modulepreload">` and `<link rel="stylesheet">` no longer become compilation entries. Inline `<script>` and `<style>` bodies are still processed. Use [`webpackIgnore`](/api/module-methods/#magic-comments) comments or the [`IgnorePlugin`](/plugins/ignore-plugin/) to skip individual URLs.
- An **array** - customize which `tag`/`attribute` pairs are treated as URLs. Include the literal string `"..."` to keep the built-in defaults; an array without `"..."` opts out of the defaults entirely.

Each array entry object accepts:

- `attribute` (required) - the attribute name whose value is a URL.
- `type` (required) - how the value is parsed and bundled. One of:
- `src` - a single URL bundled as a plain asset.
- `srcset` - a `srcset`-style candidate list of plain assets.
- `script` - a classic chunk entry, like `<script src>`.
- `script-module` - an ES-module chunk entry, like `<script type="module" src>`.
- `stylesheet` - a CSS chunk entry, like `<link rel="stylesheet">`.
- `stylesheet-style` - the attribute value is treated as a full inline stylesheet (like a `<style>` body) and routed through the CSS pipeline.
- `stylesheet-style-attribute` - the attribute value is treated as a CSS block's contents (like a `style` attribute) and routed through the CSS pipeline.
- `tag` (optional) - the tag name to match. Omit to match any element.
- `filter` (optional) - `(attributes: Map<string, string>) => boolean`; return `false` to skip this entry for a given element.

```js
export default {
experiments: { html: true },
module: {
parser: {
html: {
sources: [
"...", // keep the built-in defaults
{ tag: "img", attribute: "data-src", type: "src" },
{ tag: "img", attribute: "data-srcset", type: "srcset" },
{ attribute: "data-href", type: "src" }, // any tag
],
},
},
},
};
```

#### module.parser.html.template

Transform the raw HTML source **before** the parser extracts dependencies, so URLs emitted by a templating language (Handlebars, EJS, Eta, …) are still discovered and bundled. The function runs synchronously and must return the HTML string to parse.

- Type: `(source: string, context: HtmlTemplateContext) => string`
- Available: 5.108.0+

The `context` object provides the current `module`, its `resource` path, build-dependency registration helpers (`addDependency`, `addContextDependency`, `addMissingDependency`, `addBuildDependency`), and `emitWarning` / `emitError`.

```js
export default {
experiments: { html: true },
module: {
parser: {
html: {
template: (source, { resource, addDependency }) => {
addDependency(resource);
return source
.replaceAll("{{title}}", "Hello world")
.replaceAll("{{image}}", "./image.png");
},
},
},
},
};
```

## module.noParse

`RegExp` `[RegExp]` `function(resource)` `string` `[string]`
Expand Down
74 changes: 74 additions & 0 deletions src/content/configuration/optimization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,80 @@ export default {
};
```

## optimization.inlineExports

`boolean`

<Badge text="5.108.0+" />

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.

Inlining also enables **cross-module dead-branch skipping**: when an imported constant is statically inlinable, webpack evaluates the condition that guards a branch and skips the dependencies that live only in the provably-dead branch (ESM import specifiers, `require()` calls, and dynamic `import()` calls), so the unreachable modules are never added to the bundle.

```js
// env.js
export const isDEV = false;
```

```js
// app.js
import { devOnly } from "./dev-tools";
import { isDEV } from "./env";
import { prodOnly } from "./prod-tools";

export const tools = isDEV ? devOnly : prodOnly;
```

Because `isDEV` inlines to `false`, the `devOnly` branch is dead, so `./dev-tools` is never bundled. The same holds for `require()` and dynamic `import()` calls that sit only in the dead branch.

T> Supported guard forms include ternaries (`isDEV ? A : B`), `if` statements, and the `&&`, `||`, `??` and `!` operators, including nested combinations.

## optimization.mangleExports

`boolean` `string: 'deterministic' | 'size'`
Expand Down
Loading
Loading