-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Comparing changes
Open a pull request
base repository: webpack/webpack
base: v5.107.1
head repository: webpack/webpack
compare: v5.107.2
- 19 commits
- 125 files changed
- 5 contributors
Commits on May 21, 2026
-
Configuration menu - View commit details
-
Copy full SHA for 883de7a - Browse repository at this point
Copy the full SHA 883de7aView commit details -
Configuration menu - View commit details
-
Copy full SHA for 9e8717e - Browse repository at this point
Copy the full SHA 9e8717eView commit details -
test: cover all hash placeholders across js/css/html/asset outputs wi…
…th and without realContentHash (#21009)
Configuration menu - View commit details
-
Copy full SHA for b3893ec - Browse repository at this point
Copy the full SHA b3893ecView commit details
Commits on May 22, 2026
-
Configuration menu - View commit details
-
Copy full SHA for c755747 - Browse repository at this point
Copy the full SHA c755747View commit details -
Configuration menu - View commit details
-
Copy full SHA for 7dd1824 - Browse repository at this point
Copy the full SHA 7dd1824View commit details -
Configuration menu - View commit details
-
Copy full SHA for a086147 - Browse repository at this point
Copy the full SHA a086147View commit details -
Configuration menu - View commit details
-
Copy full SHA for 7f891b0 - Browse repository at this point
Copy the full SHA 7f891b0View commit details -
Configuration menu - View commit details
-
Copy full SHA for c05beb9 - Browse repository at this point
Copy the full SHA c05beb9View commit details -
fix: include referenced module's hash in HTML source/inline-style upd…
…ateHash (#21018) * fix: include referenced module's hash in HTML source/inline-style updateHash `HtmlSourceDependency` (`<img src>`, `<link href>`, `<audio src>`, …) and `HtmlInlineStyleDependency` (`<style>`) substitute content sourced from the referenced module into the rendered HTML at code-generation time — the asset's hashed filename for `HtmlSourceDependency`, the rendered CSS text for `HtmlInlineStyleDependency`. Without `updateHash`, the HTML module's hash didn't reflect changes to the referenced module, so the extracted HTML's `[contenthash]` stayed pinned across incremental rebuilds even when the rendered bytes had changed — the same long-term caching break `CssUrlDependency.updateHash` was added to prevent for CSS `url(...)`. Fold the referenced module's `buildInfo.hash` into each dependency's `updateHash`, matching the `CssUrlDependency` pattern. Adds two watch test cases under `test/watchCases/long-term-caching/`: `html-contenthash-asset-url` (regression for the fix) and `js-contenthash-asset-url` (the analogous case for `new URL(asset, import.meta.url)`, which already worked because the asset module's hash flows through the JS chunk hash — kept as a regression guard). * docs: require changeset descriptions to be sentence-case with a trailing period Recent changesets (`cjs-require-binding-tree-shake.md`, `public-path-fullhash-length-suffix.md`, `html-entry-css-chunks-link-tags.md`, `align-html-lexer-script-data.md`, …) all open with a capital letter and end with a period — that's what makes them read as proper changelog entries when changesets is concatenated into the release `CHANGELOG.md`. Document the rule explicitly and update the inline examples ("Fix split-chunks cache key collision.", "Add `module.generator.html.extract` option.") so the guide matches the convention reviewers already enforce. Also restyles the changeset added in the previous commit to match. * refactor: drop redundant `buildInfo` undefined check in HTML updateHash `module.buildInfo` is populated by `NormalModule#build` (and the equivalent hook on other module types) before any code path that calls `updateHash` runs — module hashing happens after the build phase. Cast straight to `BuildInfo` and keep only the `.hash` check (the field itself is still typed as optional on `KnownBuildInfo`). Matches what reviewers were flagging on the prior commit. * fix: recurse into inline-style module updateHash so transitive url() asset changes invalidate the HTML `HtmlInlineStyleDependency.Template.apply` pulls the rendered CSS text out of `codeGenerationResults` and substitutes it into the HTML — the rendered text already has every `url(...)` rewritten to its hashed asset filename by `CssUrlDependency`. The previous `updateHash` only folded the CSS module's `buildInfo.hash`, which captures the CSS *source*. The CSS source doesn't change when only the referenced asset's bytes change — that change rides on `CssUrlDependency.updateHash`, which contributes to the CSS module's *module* hash, not its `buildInfo.hash`. So the HTML's `[contenthash]` stayed pinned even though the rendered HTML embedded a new asset filename. Recurse into the inline-CSS module's full `updateHash` so the same asset-hash chain that already invalidates a standalone CSS chunk's contenthash now also invalidates the host HTML's. Adds `test/watchCases/long-term-caching/html-contenthash-inline-style-url/`, which fails before the fix (HTML filename stayed `page.36e6bef5…html` across the asset swap) and passes after. * fix: defer chunk-URL substitution in extracted HTML until chunk hashes are computed `HtmlInlineScriptDependency` and `HtmlScriptSrcDependency` (the new experimental HTML pipeline) used to call `compilation.getPath(chunk filenameTemplate, …)` from their `Template#apply` — i.e. during `Compilation#codeGeneration()`. That runs before `createHash()`, so `chunk.hash` and `chunk.contentHash[type]` are still `null`. Any `output.chunkFilename` (or `output.filename`) containing `[contenthash]` / `[chunkhash]` / `[fullhash]` would throw "Path variable [contenthash] not implemented in this context" from `TemplatedPathPlugin`, breaking every HTML compile that wanted hashed JS/CSS filenames. Even when the template happened to resolve, the HTML module's own `[contenthash]` was computed from placeholder-substituted bytes — so changing only an inline-script's transitive dep flipped the embedded chunk URL but left the HTML's `[contenthash]` pinned. Defer the substitution instead: dep templates now emit a sentinel (`__WEBPACK_HTML_CHUNK_URL__<hexChunkId>__<contentHashType>__END__`) via `makeHtmlChunkUrlSentinel` from a new `lib/html/htmlChunkUrl.js` helper, and `HtmlModulesPlugin#renderManifest` swaps every sentinel for `${PUBLIC_PATH_AUTO}<chunkFilename>` *before* hashing the HTML output — by that point `createHash()` has populated every chunk's `chunk.contentHash[type]`/`chunk.hash`/`compilation.hash`, so the chunk filenames' placeholders all resolve. Hashing the resolved content (rather than the raw placeholder source) is what makes the HTML's `[contenthash]` invalidate when a referenced chunk's filename changes. `HtmlGenerator#_renderHtml`'s JS-export path resolves sentinels inline too via the same helper; sentinels whose templates can't be resolved yet (e.g. an unbuildable `[contenthash]` placeholder at code-gen time) are left in place rather than thrown — `extract: true` (the HTML output path) is the one that supports dynamic filenames, and the JS export of the HTML string carries the restriction that previously surfaced as a compile-time error. Adds `test/watchCases/long-term-caching/html-contenthash-inline-script/`, which fails before the fix (compile errors with `[contenthash]` in `chunkFilename`) and after step 1 verifies the HTML invalidates when the inline-script's transitive dep flips. * refactor(html): extract duplicated `[contenthash]` recipe into HtmlModulesPlugin.computeContentHash `renderManifest` hashed HTML bytes twice with identical boilerplate — once for the `[contenthash]` substituted into `output.htmlFilename` and once for the final asset cache key — each call re-implementing the `createHash(hashFunction)` + `hashSalt` + `digest(hashDigest)` + `nonNumericOnlyHash(_, hashDigestLength)` recipe. Pull both call sites into a single static method on `HtmlModulesPlugin` so the recipe can't drift between them, and so anyone reaching for "the HTML pipeline's `[contenthash]` recipe" has a named entry point. No behaviour change; the previously inlined `createHash` / `nonNumericOnlyHash` requires are now inside the static method. * refactor(html): fold chunk-URL sentinel helpers into HtmlGenerator as static methods `lib/html/htmlChunkUrl.js` was a single-file module exporting the `makeHtmlChunkUrlSentinel` / `resolveHtmlChunkUrlSentinels` pair created in the previous commit. Inline them onto `HtmlGenerator` as `HtmlGenerator.makeChunkUrlSentinel` and `HtmlGenerator.resolveChunkUrlSentinels` — that's the class responsible for emitting both sides of the substitution (`_renderHtml` writes sentinels via dep templates and resolves them on the JS-export path), so it's the natural home for the sentinel format. `HtmlGenerator` doesn't import the HTML dependencies, so the two dep templates (`HtmlInlineScriptDependency`, `HtmlScriptSrcDependency`) can require it directly without introducing a circular import. `HtmlModulesPlugin` already imports `HtmlGenerator` and reaches the resolver through the same static method. No behaviour change; just removes the standalone helper file. * refactor(html): drop unnecessary chunk.id null-checks in chunk-URL sentinel helpers Both `HtmlGenerator.makeChunkUrlSentinel` (called from dep templates during `Compilation#codeGeneration()`) and `HtmlGenerator.resolveChunkUrlSentinels` (called from `_renderHtml`'s JS-export path and from `HtmlModulesPlugin#renderManifest`) run after `Compilation#seal`'s `optimizeChunkIds` hook, which is what `chunkIds`/`NamedChunkIdsPlugin`/`DeterministicChunkIdsPlugin` use to populate every chunk's `.id`. By the time these helpers run, every chunk has a non-null id, so the defensive `chunk.id == null` branches were dead code. * docs: require code comments to stay short and informative Adds a REQUIRED "Code comments" section to `AGENTS.md`: comments inside `lib/`, `hot/`, `tooling/`, `test/` must be one or at most two short lines and every line must add information not obvious from the code (invariant, ordering constraint, pinned-bug workaround, higher-level concept name). No multi-paragraph essays, no restating the next line, no diff narration, no PR-body restatements, no task-framing quotes. JSDoc on exported symbols is exempt because it's the type contract. Also trims the verbose comments added in this branch (chunk-URL sentinel docs on `HtmlGenerator`, the dep-template apply blocks, the `HtmlInlineStyleDependency` / `HtmlSourceDependency` `updateHash` explanations, `HtmlModulesPlugin.computeContentHash` JSDoc, and the renderManifest "resolve before hashing" comment) to fit the rule — 105 lines removed, no behaviour change. Pre-existing comments in other functions are left for their respective authors to revisit. * fix: address Copilot review on PR #21018 - `HtmlModulesPlugin.computeContentHash` passes `outputOptions.hashFunction` through to `createHash` typed as `HashFunction` instead of casting to `string`, so the constructor-function form of `output.hashFunction` keeps working. - Shorten the inline-script-chunk-url-sentinel changeset to fit the ≤80-char/no-commas guidance the previous commit added to AGENTS.md. - Trim the test-fixture explanatory comments Copilot flagged in `js-contenthash-asset-url/{0,2}`, `html-contenthash-asset-url/{0,2}`, `html-contenthash-inline-style-url/{0,2}`, and `html-contenthash-inline-script/{0/page.html,1/index.js}` — the test names already convey intent. No assertion logic changed. * fix: resolve chunk-URL sentinels in JS-export bundles too via processAssets The JS-export path in `HtmlGenerator._renderHtml` was leaving unresolved `__WEBPACK_HTML_CHUNK_URL__…__END__` sentinels in `module.exports = "<html>"` when chunk filenames carried `[contenthash]` / `[chunkhash]` / `[fullhash]` — chunk hashes don't exist at code-gen time, so the inline `compilation.getPath` fell into the catch and left the sentinel. Consumers doing `require("./page.html")` then saw the sentinel string at runtime. Drop the JS-export path's inline sentinel resolution entirely (it always leaves sentinels now) and add a global `processAssets` pass in `HtmlModulesPlugin` at `PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE` that sweeps every asset, resolves any surviving sentinels via `HtmlGenerator.resolveChunkUrlSentinels`, and collapses the freshly-emitted `[webpack/auto]` placeholders to `""` (root-relative — matching the prior JS-export behaviour). Stage choice matters: it runs after `createHash()` has populated every `chunk.hash` / `chunk.contentHash[type]`, so chunk filename templates resolve, and before `PROCESS_ASSETS_STAGE_OPTIMIZE_HASH` where `realContentHash` rehashes affected chunk filenames against the resolved bytes. Adds a step-0 assertion in `html-contenthash-inline-script/0/index.js` that reads `main.<hash>.js` from disk and verifies no `__WEBPACK_HTML_CHUNK_URL__<hex>__<type>__END__` survives into the JS bundle's HTML export. * fix: reuse sentinel-resolved asset source across compilations The new `processAssets` sweep was minting a fresh `RawSource` on every compilation, even when the resolved bytes were byte-identical to the previous run. `getLazyHashedEtag`'s WeakMap is keyed by source identity, and `MemoryCachePlugin` / `PackFileCacheStrategy` compare etags with reference equality, so a new source object meant a fresh `LazyHashedEtag` → fresh `MergedEtag` → cache miss → `set()` on `RealContentHashPlugin|analyse|<asset>` → "Pack got invalid because of write to" infra log. `ConfigCacheTestCases` treats that log as a failure on the 2nd (warm) run, so every HTML test with an inline script chunk regressed. Cache the resolved `RawSource` per asset name in a plugin-scoped Map and reuse it whenever the freshly-computed `resolved` string matches the prior content. Same bytes ⇒ same source object ⇒ same etag ⇒ the analyse cache hits and no infrastructure log fires. * refactor: address Copilot perf + comment-length feedback - `HtmlGenerator.resolveChunkUrlSentinels` now caches the per-compilation `chunksById` map in a module-level `WeakMap` instead of rebuilding it on every call (was O(assets × chunks) with the new `processAssets` sweep, now O(chunks) per compilation). - `HtmlModulesPlugin`'s `processAssets` pass uses `Buffer#indexOf` on Buffer-backed sources and skips them when the ASCII sentinel marker isn't present, avoiding a full UTF-8 decode of large binary blobs. - Trim multi-line explanatory comments down to ≤2 lines per the REQUIRED `AGENTS.md` rule in `lib/` and `test/`. - Shorten the changeset description to ≤80 chars. * test: drop unused step-2 `tag` in js-contenthash-asset-url * refactor: resolve sentinels at JS chunk render time, not processAssets `processAssets` is too late: any plugin that reads the chunk source between `createChunkAssets` and the `OPTIMIZE_INLINE` stage — `SourceMapDevToolPlugin` (stage 500), size-optimize plugins (stage 400), banner injection, etc. — would see unresolved `__WEBPACK_HTML_CHUNK_URL__…__END__` placeholders embedded in the JS module's export string. Tap `JavascriptModulesPlugin.getCompilationHooks(compilation).render` instead — fires for every JS chunk after `createHash` populates the content hashes (so `getPath` resolves `[contenthash]` / `[chunkhash]` / `[fullhash]`) and *during* chunk asset assembly, so the source every later pass reads is already sentinel-free. The per-chunk RawSource identity cache stays in place so warm rebuilds with byte-identical output keep the same source object and don't invalidate `RealContentHashPlugin|analyse`. * refactor: prune sentinel-resolved source cache in afterSeal Address Copilot review: in long-running watch sessions, chunks that get removed from the graph (e.g. a dynamic import the user just deleted) would leave their entries behind in the per-chunk RawSource cache forever. Tap `compilation.hooks.afterSeal` to drop entries for chunk IDs no longer in `compilation.chunks`. Also shorten the render- tap comment to two lines per the AGENTS.md rule. * refactor: trim two more multi-line comments to two lines Address Copilot review — shorten the `sentinelResolvedSourceCache` declaration comment (4 lines → 2) and the `afterSeal` prune comment (3 lines → 2) per the AGENTS.md "Code comments" REQUIRED rule. * docs: refresh stale processAssets mention in JS-export comment The JS-export-path comment in HtmlGenerator still pointed at the old `processAssets` resolution pass; that moved to `JavascriptModulesPlugin.render` in abaaf97. Update the comment to match.
Configuration menu - View commit details
-
Copy full SHA for 26e346a - Browse repository at this point
Copy the full SHA 26e346aView commit details -
fix(ConcatenatedModule): include runtimeCondition of external infos i…
…n updateHash (#21023) * docs(JavascriptParser): correct TODO referring to import phases not assertions * fix(ConcatenatedModule): include runtimeCondition of external infos in updateHash * test(ConcatenatedModule): add integration regression test for runtimeCondition hashing * revert: remove programmatic integration test in favor of configCases-style * test(ConcatenatedModule): add configCase regression test for runtimeCondition hashing * test(ConcatenatedModule): drop unit test; configCase uses real UMD external info * fix(test): cast ConcatenatedModule to bypass private member type checks in test plugin * fix(ConcatenatedModule): delimit moduleId and runtimeCondition in hash to avoid collisions * fix(ConcatenatedModule): also hash nonDeferAccess and isDeferred for external infos
Configuration menu - View commit details
-
Copy full SHA for 75f60f6 - Browse repository at this point
Copy the full SHA 75f60f6View commit details
Commits on May 23, 2026
-
docs(buildChunkGraph): explain why blocksWithNestedBlocks gates the s…
…kip (#21025) * docs(buildChunkGraph): explain why blocksWithNestedBlocks gates the skip The previous `// TODO is this needed?` left the rationale ambiguous. Skipping a block disconnects it from its chunk group, which orphans any nested block's chunk group from this block's chunk group parent, so the check must stay. * test(chunks): cover the blocksWithNestedBlocks skip guard Pins down the case where buildChunkGraph's connectChunkGroups would otherwise skip a block whose modules are already in the entry chunk. Without the `!blocksWithNestedBlocks.has(block)` guard, the outer require.ensure's chunk group is left without a parent and gets cleaned up together with the nested chunk group, so the inner sync require fails at runtime. With the guard the test passes; removing the guard makes the test time out waiting for the inner callback.
Configuration menu - View commit details
-
Copy full SHA for 12cb825 - Browse repository at this point
Copy the full SHA 12cb825View commit details
Commits on May 25, 2026
-
Configuration menu - View commit details
-
Copy full SHA for cc4035b - Browse repository at this point
Copy the full SHA cc4035bView commit details -
docs: update examples (#21031)
Co-authored-by: alexander-akait <4567934+alexander-akait@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for a514897 - Browse repository at this point
Copy the full SHA a514897View commit details -
Configuration menu - View commit details
-
Copy full SHA for c61c649 - Browse repository at this point
Copy the full SHA c61c649View commit details -
Configuration menu - View commit details
-
Copy full SHA for 78158f0 - Browse repository at this point
Copy the full SHA 78158f0View commit details -
Configuration menu - View commit details
-
Copy full SHA for c073890 - Browse repository at this point
Copy the full SHA c073890View commit details -
Configuration menu - View commit details
-
Copy full SHA for d6cdebe - Browse repository at this point
Copy the full SHA d6cdebeView commit details -
Configuration menu - View commit details
-
Copy full SHA for c7d8a3a - Browse repository at this point
Copy the full SHA c7d8a3aView commit details -
chore(release): new release (#21019)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for cfb24a4 - Browse repository at this point
Copy the full SHA cfb24a4View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v5.107.1...v5.107.2