Skip to content
Merged
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
9 changes: 6 additions & 3 deletions src/content/concepts/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -138,18 +138,21 @@ In order to use a plugin, you need to `import` it and add it to the `plugins` ar
**webpack.config.js**

```js
import HtmlWebpackPlugin from "html-webpack-plugin";
import webpack from "webpack"; // to access built-in plugins

export default {
entry: "./src/index.html",
experiments: {
html: true,
},
module: {
rules: [{ test: /\.js$/, use: "babel-loader" }],
},
plugins: [new HtmlWebpackPlugin({ template: "./src/index.html" })],
plugins: [new webpack.ProgressPlugin()],
};
```

In the example above, the `html-webpack-plugin` generates an HTML file for your application and automatically injects all your generated bundles into this file.
In the example above, the `ProgressPlugin` customizes how build progress is reported. Your `src/index.html` is the entry: webpack bundles the scripts and styles it references and rewrites those URLs to the built filenames, so no plugin is needed to produce the page — see [Native HTML](/guides/native-html/).

T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins).

Expand Down
2 changes: 1 addition & 1 deletion src/content/concepts/loaders.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default {
};
```

T> Plain `.css` files need no loader at all: webpack parses, extracts and minifies CSS itself — see [`experiments.css`](/configuration/experiments/#experimentscss) and the [Native CSS](/guides/native-css/) guide. A preprocessor still needs its loader, and `type: 'css/auto'` hands what the loader produces to webpack's CSS pipeline.
T> Plain `.css` files need no loader at all: webpack has experimental built-in CSS support that parses, extracts and minifies CSS itself — see [`experiments.css`](/configuration/experiments/#experimentscss) and the [Native CSS](/guides/native-css/) guide. A preprocessor still needs its loader, and `type: 'css/auto'` hands what the loader produces to webpack's CSS pipeline.

## Using Loaders

Expand Down
13 changes: 6 additions & 7 deletions src/content/concepts/plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ Depending on how you are using webpack, there are multiple ways to use plugins.
```js
import path from "node:path";
import { fileURLToPath } from "node:url";
import HtmlWebpackPlugin from "html-webpack-plugin";
import webpack from "webpack"; // to access built-in plugins

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
entry: "./path/to/my/entry/file.js",
entry: "./src/index.html",
experiments: {
html: true,
},
output: {
filename: "my-first-webpack.bundle.js",
path: path.resolve(__dirname, "dist"),
Expand All @@ -72,14 +74,11 @@ export default {
},
],
},
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({ template: "./src/index.html" }),
],
plugins: [new webpack.ProgressPlugin()],
};
```

The `ProgressPlugin` is used to customize how progress should be reported during compilation, and `HtmlWebpackPlugin` will generate a HTML file including the `my-first-webpack.bundle.js` file using a `script` tag.
The `ProgressPlugin` is used to customize how progress should be reported during compilation. `src/index.html` is the entry, so webpack emits it as the page with the `<script src>` it references rewritten to the built chunk — no plugin is needed for that, see [Native HTML](/guides/native-html/).

### Node API

Expand Down
7 changes: 4 additions & 3 deletions src/content/configuration/configuration-languages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,16 @@ and then proceed to write your configuration:
```coffeescript
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import webpack from 'webpack'

__filename = fileURLToPath(import.meta.url)
__dirname = path.dirname(__filename)

config =
mode: 'production'
entry: './path/to/my/entry/file.js'
entry: './src/index.html'
experiments:
html: true
output:
path: path.resolve(__dirname, 'dist')
filename: 'my-first-webpack.bundle.js'
Expand All @@ -206,7 +207,7 @@ config =
}
]
plugins: [
new HtmlWebpackPlugin(template: './src/index.html')
new webpack.ProgressPlugin()
]

export default config
Expand Down
2 changes: 1 addition & 1 deletion src/content/guides/asset-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Webpack understands CSS on its own, so you can `import` a CSS file from a JavaSc
import "./style.css";
```

Webpack parses the file — resolving its `@import` and `url()` references — and extracts it into a `.css` output file next to your bundle. CSS Modules, minification and content hashes all come from the same built-in support; the [Native CSS](/guides/native-css/) guide covers the whole feature set.
Webpack parses the file — resolving its `@import` and `url()` references — and extracts it into a `.css` output file next to your bundle. CSS Modules, minification and content hashes all come from the same built-in support, which is still experimental; [What's built-in](/guides/native-css/#whats-built-in) states what it covers and what still needs a loader.

T> Built-in CSS is controlled by [`experiments.css`](/configuration/experiments/#experimentscss), which defaults to `'auto'`: it turns itself on unless a `module.rules` entry with a loader already matches your `.css` files. That means an existing `css-loader` / `style-loader` setup keeps working untouched — see [migrating off the CSS loaders](/guides/native-css/#migration-guide).

Expand Down
2 changes: 2 additions & 0 deletions src/content/guides/caching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ We can use the `output.filename` [substitutions](/configuration/output/#outputfi

Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually:

T> Webpack can generate the page itself with [`output.html`](/configuration/output/#outputhtml) — see [Native HTML](/guides/native-html/). This guide keeps `HtmlWebpackPlugin` because the generated page re-enters the entry's script under an internal chunk name, which would obscure the bundle filenames this guide is about.

**project**

```diff
Expand Down
2 changes: 2 additions & 0 deletions src/content/guides/development.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ The only downside is that you have to refresh your browser in order to see the c

### Using webpack-dev-server

T> Webpack can generate the page itself with [`output.html`](/configuration/output/#outputhtml) — see [Native HTML](/guides/native-html/). This guide keeps `HtmlWebpackPlugin` because it emits one page per entrypoint rather than a single page carrying every entry's script, so the output here would not be the same.

The `webpack-dev-server` provides you with a rudimentary web server and the ability to use live reloading. Let's set it up:

```bash
Expand Down
2 changes: 2 additions & 0 deletions src/content/guides/hot-module-replacement.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ W> **HMR** is not intended for use in production, meaning it should only be used

## Enabling HMR

T> Webpack can generate the page itself with [`output.html`](/configuration/output/#outputhtml) — see [Native HTML](/guides/native-html/). This guide keeps `HtmlWebpackPlugin` because it emits one page per entrypoint rather than a single page carrying every entry's script, so the output here would not be the same.

This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built-in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module.

Since `webpack-dev-server` v4.0.0, Hot Module Replacement is enabled by default.
Expand Down
13 changes: 11 additions & 2 deletions src/content/guides/modern-web-platform.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -160,21 +160,30 @@ npm install workbox-webpack-plugin workbox-precaching --save-dev
```js
import path from "node:path";
import { fileURLToPath } from "node:url";
import HtmlWebpackPlugin from "html-webpack-plugin";
import { InjectManifest } from "workbox-webpack-plugin";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
entry: "./src/index.js",
experiments: {
html: true,
},
output: {
filename: "[name].[contenthash].js",
htmlFilename: "index.html",
path: path.resolve(__dirname, "dist"),
clean: true,
html: {
title: "PWA + content hashes",
meta: {
charset: "utf8",
viewport: "width=device-width, initial-scale=1",
},
},
},
plugins: [
new HtmlWebpackPlugin({ title: "PWA + content hashes" }),
new InjectManifest({
swSrc: path.resolve(__dirname, "src/service-worker.js"),
swDest: "service-worker.js",
Expand Down
17 changes: 16 additions & 1 deletion src/content/guides/native-css.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,22 @@ export default {
};
```

With this option enabled, webpack understands `.css` files as first-class modules — parsing `@import` and `url()`, extracting stylesheets, generating content hashes, minifying, and supporting CSS Modules — without `css-loader`, `style-loader`, `mini-css-extract-plugin`, or `css-minimizer-webpack-plugin`.
With this option enabled, webpack understands `.css` files as first-class modules: it parses them itself instead of handing them to a loader.

## What's built-in

"Built-in" means webpack does the work itself, with no loader in the chain — not that it covers everything the CSS loaders do. The scope is exactly this:

| Built in | Still needs a loader or plugin |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Parsing `.css`; resolving `@import` and `url()` / `image-set()` / `src()` / `image()` | **Preprocessors** — Sass, Less, Stylus and PostCSS always keep their loaders |
| [CSS Modules](#css-modules): `composes`, `@value`, `:export`, `:local()` / `:global()` | `css-loader`'s `importLoaders`, `localIdentRegExp`, `getJSON`, and the `url` / `import` filter callbacks |
| [Extracting](#output-modes-exporttype) a `.css` file, or injecting a `<style>` tag at runtime | `style-loader`'s `insert`, `attributes`, `styleTagTransform`, and its lazy / singleton injection modes |
| Content hashes, [minification](#minification) and browserslist [vendor prefixes](#vendor-prefixes) | Anything a PostCSS plugin does beyond `@custom-media` / `@custom-selector` |
| [`@custom-media` and `@custom-selector`](#custom-media-and-custom-selectors) | |
| Hot Module Replacement for stylesheets | |

So a project whose CSS setup is `css-loader` + `style-loader` (or `mini-css-extract-plugin`) with default options needs no CSS loader at all. A project that reaches for the options in the right-hand column keeps that loader for the files that need it — the two can coexist, rule by rule.

T> Since webpack 5.109.0 the option defaults to `'auto'`: built-in CSS support turns on unless a [`module.rules`](/configuration/module/#modulerules) entry with a loader (or an explicit module type) already matches `.css` files. An existing `css-loader` setup therefore keeps working untouched, and you can migrate one rule at a time. Set it to `true` to force the native support, or `false` to switch it off.

Expand Down
21 changes: 19 additions & 2 deletions src/content/guides/native-html.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,22 @@ export default {
};
```

With this option enabled, webpack understands `.html` files as first-class modules — parsing tags, resolving every URL they reference, bundling inline `<script>` and `<style>` bodies, emitting hashed assets, and writing the rewritten HTML back out — without `html-loader` or `html-webpack-plugin`.
With this option enabled, webpack understands `.html` files as first-class modules: it parses them itself instead of handing them to a loader.

## What's built-in

"Built-in" means webpack does the work itself, with no loader or plugin in the chain — not that it covers everything `html-loader` and `html-webpack-plugin` do. The scope is exactly this:

| Built in | Still needs a loader or plugin |
| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Parsing `.html`, as an [entry point](#1-html-as-an-entry-point) or [imported from JS](#3-html-imported-from-javascript) | **Template engines** — Pug, EJS, Handlebars and friends, unless a synchronous [`template`](#templating) hook is enough |
| [Extracting every URL a page references](#what-webpack-bundles-from-a-page) and rewriting it to the built filename | `html-loader`'s `sources.scriptingEnabled` and `postprocessor` |
| Bundling inline `<script>` and `<style>` bodies, and `style=""` attributes | `html-webpack-plugin`'s `chunksSortMode`, `xhtml`, `showErrors` and `cache` |
| [Generating a page](#2-a-generated-page-for-a-javascript-entry) per entrypoint with its chunks injected | The third-party plugins that tap `html-webpack-plugin`'s hooks, which have no counterpart on [`HtmlModulesPlugin`](#plugin-hooks) yet |
| [`title`, `meta`, `base`, `favicon`, `manifest`, `integrity`, `csp`, inlining](#configuring-the-generated-page) | |
| [Minification](#minification) and Hot Module Replacement | |

So a project using `html-webpack-plugin` to scaffold a document around its bundles, or `html-loader` to import a partial, needs neither. A project that renders its page through a template engine, or depends on a plugin that hooks into `html-webpack-plugin`, keeps that plugin.

T> Since webpack 5.109.0 the option defaults to `'auto'`: built-in HTML support turns on unless a [`module.rules`](/configuration/module/#modulerules) entry with a loader (or an explicit module type) already matches `.html` files. An existing `html-loader` setup therefore keeps working untouched, and you can migrate one rule at a time. [`experiments.futureDefaults`](/configuration/experiments/#experimentsfuturedefaults) resolves it to `true`.

Expand Down Expand Up @@ -335,7 +350,9 @@ export default {
};
```

Every icon — including the ones named inside the manifest — is emitted as a hashed asset through the normal pipeline, so `favicons-webpack-plugin` and friends are no longer needed. Both apply to webpack-generated pages only: an authored page is left exactly as written, so add the `<link>` tags to the page itself when you own its markup. Both options also accept a function receiving the page name, which is how you give each page of a multi-page build its own icon set.
Every icon — including the ones named inside the manifest — is emitted as a hashed asset through the normal pipeline. Both options also accept a function receiving the page name, which is how you give each page of a multi-page build its own icon set.

Two limits are worth knowing. Webpack emits the icons you point it at; it does not generate the size and format variants a dedicated plugin such as `favicons-webpack-plugin` produces from one source image. And both options apply to webpack-generated pages only — an authored page is left exactly as written, so add the `<link>` tags to the page yourself when you own its markup.

### Subresource Integrity and CSP

Expand Down
2 changes: 2 additions & 0 deletions src/content/guides/output-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ Multiple entry points are used here solely to demonstrate output management and

## Setting up HtmlWebpackPlugin

T> Webpack can generate the page itself with [`output.html`](/configuration/output/#outputhtml) — see [Native HTML](/guides/native-html/). This guide keeps `HtmlWebpackPlugin` because the generated page re-enters the entry's script under an internal chunk name, which would obscure the bundle filenames this guide is about.

First install the plugin and adjust the `webpack.config.js` file:

```bash
Expand Down
18 changes: 11 additions & 7 deletions src/content/guides/production.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ npm install --save-dev webpack-merge
```diff
+ import path from 'node:path';
+ import { fileURLToPath } from 'node:url';
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
+
+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);
Expand All @@ -74,15 +73,21 @@ npm install --save-dev webpack-merge
+ entry: {
+ app: './src/index.js',
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: 'Production',
+ }),
+ ],
+ experiments: {
+ html: true,
+ },
+ output: {
+ filename: '[name].bundle.js',
+ htmlFilename: 'index.html',
+ path: path.resolve(__dirname, 'dist'),
+ clean: true,
+ html: {
+ meta: {
+ charset: 'UTF-8',
+ viewport: 'width=device-width, initial-scale=1',
+ },
+ title: 'Production',
+ },
+ },
+ };
```
Expand Down Expand Up @@ -142,7 +147,6 @@ Now, let's modify our npm scripts to use the new configuration files. For the `s
"css-loader": "^7.1.3",
"csv-loader": "^3.0.5",
"express": "^5.2.1",
"html-webpack-plugin": "^5.6.6",
"style-loader": "^4.0.0",
"webpack": "^5.105.0",
"webpack-cli": "^7.0.0",
Expand Down
2 changes: 2 additions & 0 deletions src/content/guides/progressive-web-application.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ This is what we aim to change. Once we reach the end of this module we should be

## Adding Workbox

T> Webpack can generate the page itself with [`output.html`](/configuration/output/#outputhtml) — see [Native HTML](/guides/native-html/). This guide keeps `HtmlWebpackPlugin` because it emits one page per entrypoint rather than a single page carrying every entry's script, so the output here would not be the same.

Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file:

```bash
Expand Down
Loading
Loading