Skip to content

docs: teach the docs native HTML and CSS, drop html-webpack-plugin and the CSS loaders - #8355

Merged
alexander-akait merged 7 commits into
mainfrom
claude/html-webpack-plugin-deprecation-spdnlg
Sep 8, 2026
Merged

alexander-akait merged 7 commits into
mainfrom
claude/html-webpack-plugin-deprecation-spdnlg

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Sep 8, 2026 •

Copy link
Copy Markdown
Member

webpack builds HTML and CSS natively now, so the docs should teach that first instead of routing every reader through html-webpack-plugin, mini-css-extract-plugin, css-loader and style-loader.

What changed

html-webpack-plugin is gone from the guides and reference. The guides that used it — output management, development, HMR, PWA, caching — now make the page itself an entry point (entry: "./src/index.html" with experiments.html), and webpack emits the page with its scripts injected. src/content/plugins/html-webpack-plugin.mdx is deleted, with a redirect to /guides/native-html/ in webpack.ssg.mjs.

The CSS loaders are gone too. css-loader, style-loader and MiniCssExtractPlugin no longer appear in the guides; experiments.css has defaulted to 'auto' since 5.109.0, so an imported .css file needs no loader and no plugin. Where a reader needs more, the text links to /guides/native-css/. Their pages redirect there as well, and the three packages are added to excludedLoaders/excludedPlugins in src/utilities/constants.mjs so the README fetcher stops pulling pages for them.

The front page shows the new model. The splash example is built around an HTML entry with hashed output filenames, and shows the emitted dist/index.html next to the config. The rotator gained "pages" alongside the existing asset kinds.

The native HTML guide gained migration help. The companion-plugin table now covers 13 of the plugins people pair with html-webpack-plugin, and a new "Rewriting a plugin that tapped its hooks" section maps the old hooks onto HtmlModulesPlugin's (injectTags, transformTags, transformHtml, htmlEmitted) with a worked NoModulePlugin example.

Build listings

The listings show the filenames webpack emits today, verified against webpack/webpack#22008 (merged): a page entry emits no JavaScript of its own, so the scripts it pulls in take the entry's name — main.bundle.js for the first, main1.bundle.js for the second. Before that fix an HTML entry also emitted a dead JS bundle duplicating the page markup, which is why these listings would have looked different a week ago.

Checks

lint:prettier, lint:js and lint:markdown pass locally. lint:prose needs vale, and lint:links needs a built dist, so both are left to CI here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9

alexander-akait and others added 4 commits September 7, 2026 16:18
The guide series taught HtmlWebpackPlugin and each page carried a note
explaining why it had not moved to the built-in HTML support yet. Webpack
builds pages itself, so the guides now use it and the plugin is no longer
named anywhere outside the migration guide.

output-management makes src/index.html the entry point: the page lists the
scripts it needs, webpack rewrites their URLs to the emitted bundles, and
there is no second list of entry points to keep in sync. development, HMR
and PWA follow that config through, and caching uses output.html since it
keeps a single JavaScript entry. Every build listing in those guides was
regenerated against webpack 5.110.3.

Scripts a page references become chunks of that page, so their names are
generated (__html_<hash>_<n>) rather than taken from entry. That is what
the listings show now, with a note in output-management and caching saying
where the names come from.

/plugins/html-webpack-plugin is removed and redirects to the Native HTML
guide, which documents the plugin's options and their built-in equivalents.
The plugins index links there instead of to the deleted page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9
The splash example bundled one JavaScript file and asked the reader to
write the page by hand, pointing a <script> tag at dist/bundle.js. Webpack
handles all three now, so the example starts from src/index.html: the page
links a stylesheet and a script, entry points at the page, and the emitted
document is shown next to the config with its URLs rewritten to the hashed
assets. Verified against webpack 5.110.3 — an HTML entry turns on the html
and css support on its own, and htmlFilename keeps the page's name out of
the contenthash pattern.

The migration guide's companion-plugin table now covers the popular
html-webpack-plugin ecosystem rather than five entries, and a new section
maps its six hooks onto HtmlModulesPlugin's, with a plugin rewritten
through transformTags and injectTags as the worked example.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9
… docs

Webpack handles CSS itself, so the three packages are no longer named
outside the migration guide, and their pages are gone: css-loader and
style-loader join the excluded loaders, MiniCssExtractPlugin the excluded
plugins, and /loaders/css-loader, /loaders/style-loader and
/plugins/mini-css-extract-plugin redirect to the Native CSS guide. The
exclusion entries carry the webpack/ prefix the repositories actually
have; the older webpack-contrib/ spellings around them no longer match
anything the fetcher lists.

The HMR guide stops installing style-loader and css-loader for its
stylesheet section: experiments.css defaults to 'auto', so importing a
stylesheet needs no rule at all — webpack bundles it and links it into the
page, verified against webpack 5.110.3. The remaining mentions were
reference asides (a filter option, an ident-hash comment, an exports
convention, the CSS extraction bullet) and now describe the behavior
without naming a package, linking the guide where a reader needs more.

Left alone: the Native CSS migration guide, which has to name what it
migrates from, and the release posts and the v1-to-v2 migration guide,
where the loaders are part of the record.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9
webpack/webpack#22008 gives a page's extracted scripts the entry's
filename now that the page emits no JavaScript of its own, so the guides
stop showing generated identifiers. output-management and development list
main.bundle.js and main1.bundle.js for the two scripts the page pulls in,
the PWA listing follows in the same format, and caching is back to
main.<contenthash>.js beside runtime and vendors — its note about generated
chunk names is gone and the prose names the main bundle again.

Every listing was regenerated against that branch (84c1155): a page with
two scripts emits main.bundle.js and main1.bundle.js, and the caching setup
emits main.<hash>.js, vendors.<hash>.js and runtime.<hash>.js.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9
@vercel

vercel Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
webpack-js-org Ready Ready Preview Sep 8, 2026 9:39am UTC

Request Review

@linux-foundation-easycla

linux-foundation-easycla Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

One or more co-authors of this pull request were not found. You must specify co-authors in commit message trailer via:

Co-authored-by: name <email>

Supported Co-authored-by: formats include:

  1. Anything <id+login@users.noreply.github.com> - it will locate your GitHub user by id part.
  2. Anything <login@users.noreply.github.com> - it will locate your GitHub user by login part.
  3. Anything <public-email> - it will locate your GitHub user by public-email part. Note that this email must be made public on Github.
  4. Anything <other-email> - it will locate your GitHub user by other-email part but only if that email was used before for any other CLA as a main commit author.
  5. login <any-valid-email> - it will locate your GitHub user by login part, note that login part must be at least 3 characters long.

Alternatively, if the co-author should not be included, remove the Co-authored-by: line from the commit message.

Please update your commit message(s) by doing git commit --amend and then git push [--force] and then request re-running CLA check via commenting on this pull request:

/easycla

alexander-akait and others added 2 commits September 8, 2026 09:20
The two owner-rename tests used css-loader as their example, and this
branch stops building a css-loader page, so the "has a page" assertion
no longer holds. postcss-loader is the same shape — a webpack-owned
loader the site still builds a page for — and keeps both tests testing
what they were written for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9

Copy link
Copy Markdown
Member Author

E2E test and link check is red on 46ef11f, on 1 assertion out of 48,442:

✖ FAIL fragment-check dist/plugins/diagnostics-webpack-plugin/index.html --> /configuration/other-options/#validate
| operator: fragment-check
| expected: id="validate"
|       at: dist/plugins/diagnostics-webpack-plugin/index.html:49:82

This is not caused by this PR:

  • plugins/diagnostics-webpack-plugin is not a checked-in page — fetch-package-readmes.mjs generates it at build time from the plugin's README on GitHub, so the link comes from that README, not from this branch. Nothing checked in links to that anchor (grep -rn "other-options/#validate" src/ finds nothing).
  • This branch does not touch src/content/configuration/other-options.mdx, and the target page is reached fine — only the fragment is missing.

The underlying gap: webpack has a top-level validate option (schema: "Enable validation of webpack configuration. Defaults to true in development mode. In production mode, defaults to true unless futureDefaults is enabled, then defaults to false.", and lib/config/defaults.js sets F(options, "validate", () => !(futureDefaults === true && production))), but other-options.mdx has no validate section, so the anchor the README points at does not exist. Any build of main today produces the same page and the same missing anchor.

Documenting validate is the fix, but it belongs in its own PR rather than widening this one. The patch would be a section in src/content/configuration/other-options.mdx, alphabetically after snapshot:

## validate

`boolean`

Enable validation of the webpack configuration against its schema. Defaults to `true` in development mode. In production mode it also defaults to `true`, unless [`experiments.futureDefaults`](/configuration/experiments/#experimentsfuturedefaults) is enabled, in which case it defaults to `false`.

**webpack.config.js**

\`\`\`js
module.exports = {
  //...
  validate: false,
};
\`\`\`

Re-running the job once to rule out a transient README fetch. Everything else on this head is green: Lint, Proselint, Unit Test, Socket ×2, dependency-review, Vercel, and EasyCLA.


Generated by Claude Code

diagnostics-webpack-plugin's README links to
/configuration/other-options/#validate, and the anchor did not exist:
webpack has had a top-level `validate` option since 5.106.0, and this
page never covered it. That dead fragment fails the link check on any
build, this branch included.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuWDbcF2jvq7q1r8aEY5V9
@alexander-akait
alexander-akait merged commit ea1c0cb into main Sep 8, 2026
11 checks passed
@alexander-akait
alexander-akait deleted the claude/html-webpack-plugin-deprecation-spdnlg branch September 8, 2026 09:49

This branch was successfully deployed

1 active deployment
Preview — 96ce5ebf Deployed Sep 8, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant