From 97b866f2f284e2c99bb2eaf2620f086a9c9ea3f1 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sat, 29 Aug 2026 13:41:58 -0500 Subject: [PATCH 1/7] docs(blog): add the webpack 5.110 release post Covers the performance hint suite, built-in CSS and HTML minification, the native CSS story, the nodeModules externals preset, the glob rule condition and the rest of the release. The benchmark table comparing the native pipeline with the loader one is a placeholder pending real measurements, and the banner image still has to be added. Co-Authored-By: Claude Opus 5 (1M context) --- src/content/blog/2026-08-26-webpack-5-110.mdx | 308 ++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 src/content/blog/2026-08-26-webpack-5-110.mdx diff --git a/src/content/blog/2026-08-26-webpack-5-110.mdx b/src/content/blog/2026-08-26-webpack-5-110.mdx new file mode 100644 index 000000000000..29ca473afa04 --- /dev/null +++ b/src/content/blog/2026-08-26-webpack-5-110.mdx @@ -0,0 +1,308 @@ +--- +title: Webpack 5.110 +sort: 20260826 +contributors: + - bjohansebas +--- + +Webpack 5.110 is out. The headline is that webpack now tells you what is wrong with your bundle: a suite of more than thirty performance checks that report duplicated packages, modules nothing uses, chunks that load in a waterfall, rules that never match, and the rest of the things people used to reach for a plugin or a bundle analyzer to find. + +The second story is that the built-in minimizer now handles CSS and HTML as well as JavaScript, with every rewrite it may perform exposed as an option. Together with the native CSS support that has been maturing since 5.107, that closes the last gap between webpack's own CSS pipeline and the loader-based one, and it is why this release also announces the deprecation of `css-loader`, `style-loader` and `mini-css-extract-plugin`. + +Explore what's new: + +- [**Performance Hints**](#performance-hints) + - [Turning them on](#turning-them-on) + - [What each check looks at](#what-each-check-looks-at) + - [Reporting into stats only](#reporting-into-stats-only) +- [**CSS and HTML Minification, Built In**](#css-and-html-minification-built-in) + - [Configuring the minimizer per asset type](#configuring-the-minimizer-per-asset-type) +- [**Native CSS Is the Way Forward**](#native-css-is-the-way-forward) + - [Benchmarks](#benchmarks) + - [Migrating](#migrating) +- [**Externalizing Installed Packages**](#externalizing-installed-packages) +- [**OS-Independent Module Rules**](#os-independent-module-rules) +- [**Tree Shaking and Scope Hoisting**](#tree-shaking-and-scope-hoisting) +- [**Server-Side Rendering**](#server-side-rendering) +- [**HTML Improvements**](#html-improvements) +- [**Output and Library**](#output-and-library) +- [**MultiCompiler**](#multicompiler) +- [**Other Improvements**](#other-improvements) +- [**Bug Fixes and Performance**](#bug-fixes-and-performance) + +## Performance Hints + +`performance` used to do one thing: warn when an asset or an entrypoint went over a size budget. In 5.110 it becomes the place where webpack reports everything it noticed about your build while it was making it. + +The checks fall into two groups. Some look at the bundle: packages included twice, modules shipped by several entrypoints, a barrel file dragging in code nothing uses, a chunk carried by a single module, `import()` calls that defer nothing. Others look at the configuration: a `module.rules` entry that never matched, a `resolve.alias` nothing resolved through, a `DefinePlugin` key no module reads, an `externals` request nothing imported, a `test` that only matches on one operating system. + +None of it is guesswork from outside the build. webpack already has the module graph, the chunk graph, the resolver's answers and the rule set, so each check reads the thing it is reporting on. + +### Turning them on + +Every check is off by default. [`performance.all`](/configuration/performance/#performanceall) turns on the whole set, and anything you set explicitly still wins: + +```js +export default { + // ... + performance: { + hints: "warning", + all: true, + }, +}; +``` + +That is the configuration to audit a project with. Once you have read the report, keep the handful that matter to you and leave the rest off, since several of the checks walk the module graph and cost build time. + +A single check works the same way: + +```js +export default { + // ... + performance: { + hints: "warning", + duplicatePackages: true, + unusedRules: true, + }, +}; +``` + +### What each check looks at + +| Area | Checks | +| ------------------- | ------------------------------------------------------------------------------------------------------------------ | +| What ships twice | `duplicatePackages`, `duplicateModules`, `entrypointOverlap` | +| What ships unused | `unusedReexports`, `missingSideEffects`, `dynamicExports`, `scopeHoistingBailouts`, `legacyJavascript` | +| How chunks load | `asyncChunkWaterfalls`, `redundantDynamicImports`, `tinyChunks`, `unsplitVendors`, `splitChunksCapped` | +| What weighs a chunk | `largeModules`, `inlinedAssets`, `embeddedSourceMaps`, `broadContexts` | +| Code hazards | `evalUsage`, `pureAnnotations`, `topLevelThis`, `mixedExports` | +| Configuration | `unusedRules`, `unusedAliases`, `unusedDefines`, `unusedExternals`, `osDependentRules`, `conflictingResourceHints` | +| Build itself | `cacheEffectiveness`, `hotspots`, `circularDependencies` | + +Each one is documented under [`performance`](/configuration/performance/#available-checks), with what it reports and what to do about it. + +Each hint says what it found, what it costs and what to do about it. A duplicate package report names the versions and the bytes; a scope hoisting report groups the bailouts by reason rather than listing every module; [`hotspots`](/configuration/performance/#performancehotspots) times each loader, plugin and hook's own synchronous code rather than what it waited for, so it points at the thing that is actually slow. + +The configuration checks are not gated on `hints`. A rule nothing matches or a misspelled external is a mistake rather than a size, so they are reported whenever the check itself is on. + +### Reporting into stats only + +Turning on twenty checks in a project that has never had them is a lot of warnings, and in CI a lot of failures. [`performance.hints: "stats"`](/configuration/performance/#performancehints) collects the hints into [`stats`](/configuration/stats/#statshints) instead of emitting them as warnings or errors, so the build stays green while you work through the report: + +```js +export default { + // ... + performance: { + hints: "stats", + all: true, + }, +}; +``` + +Hints are also now computed after hashing, so turning one on does not change your output hashes, and they are reported in a stable order when entries tie. + +## CSS and HTML Minification, Built In + +When [`optimization.minimize`](/configuration/optimization/#optimizationminimize) is enabled, webpack's default minimizer now minifies CSS and HTML assets as well as JavaScript, through the same worker pool. If you already have a minimizer configured for those assets, webpack steps aside and leaves them to it. + +Both minifiers are conservative by construction: they only make transformations an engine cannot tell apart. + +The CSS side folds `calc()` and the other math functions over constants, merges box longhands into the shorthand they are, writes each color, number, selector and media query in its shortest equal spelling, drops rules a later identical one makes dead, and maintains vendor prefixes against your `browserslist` target. + +The HTML side leaves out the tags the parser re-implies, collapses whitespace nothing renders, normalizes attribute quoting and casing, and rewrites `style`, token lists, `srcset`, `sizes` and a JSON `