Support inline hash digest/length in path placeholders and CSS localIdentName#21259
Conversation
…olders Normalize css-loader / loader-utils style `[hash:<digest>:<length>]` placeholders in the native CSS generator: fold the digest and length into the local ident hash options and map `[hash]`/`[fullhash]` to the local ident hash (css-loader semantics) so suffixed placeholders like `[fullhash:6]` and `[hash:base64:6]` work.
Extend TemplatedPathPlugin.interpolate to accept `[hash:<digest>:<length>]` (e.g. `[contenthash:base64:8]`) for filename/path templates, re-encoding the stored hash into the requested digest. The source hash is already truncated to output.hashDigestLength, so the result derives from those bytes.
Drop the css-loader-specific localIdentName hash remapping; inline digest and length are handled generically in TemplatedPathPlugin.interpolate.
Make the localIdent hash-detection regexes suffix-tolerant so [fullhash:N] and [contenthash:...] trigger hash computation, and pass the output digest into interpolate so an inline digest on [hash]/[contenthash] re-encodes correctly.
Export getPresentKinds as the single source of truth for which [kind] placeholders a template references, and route CssGenerator, RuntimePlugin and SourceMapDevToolPlugin through it instead of their own hand-rolled regexes so they can't drift from interpolate's grammar.
Re-encoding silently kept the source encoding for a typo'd digest; validate the requested digest and throw a clear error instead, matching how interpolate already rejects unimplemented path variables.
Inline-digest path re-encoded the hashDigestLength-truncated hash, capping entropy below the requested length. Pass the untruncated compilation/chunk hash (which already exists) so [fullhash:<digest>] and [chunkhash:<digest>] carry full entropy and match an encode-then-slice result.
RealContentHashPlugin recomputes content hashes in output.hashDigest and would silently overwrite an inline-digest [contenthash] with a hex hash. Throw a clear error for that combination instead of emitting the wrong encoding.
The local ident hash uses localIdentHashDigest, not output.hashDigest, so an inline [fullhash:<digest>] re-encoded from the wrong source. Pass the untruncated local ident hash and its own digest (fullHashDigest) so interpolate re-encodes it correctly with full entropy.
The contentHash producers all did nonNumericOnlyHash(hash.digest(d), n); wrap that composition in one helper and route JavascriptModulesPlugin, CssModulesPlugin, HtmlModulesPlugin and getLocalIdent through it. AssetGenerator keeps the inline form since it also returns the untruncated digest.
…dule hash Fixes issue point 2: the module-context block in interpolate repurposed [hash] to the module hash, diverging from css-loader. Add a data.hashAsFullHash flag that getLocalIdent sets so [hash] stays the local ident hash (like [fullhash]); [modulehash] still yields the module hash. Closes #21141 (point 2).
🦋 Changeset detectedLatest commit: 6f44114 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
This PR is packaged and the instant preview is available (ecc00c0). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@ecc00c0
yarn add -D webpack@https://pkg.pr.new/webpack@ecc00c0
pnpm add -D webpack@https://pkg.pr.new/webpack@ecc00c0 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21259 +/- ##
=======================================
Coverage 92.80% 92.80%
=======================================
Files 590 591 +1
Lines 64647 64726 +79
Branches 17993 18040 +47
=======================================
+ Hits 59996 60071 +75
- Misses 4651 4655 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merging this PR will improve performance by 25.06%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing |
Summary
Closes #21141 (both points). Adds css-loader / loader-utils style inline hash digest and length to webpack's path placeholders —
[<hash>:<digest>:<length>](e.g.[contenthash:base64:8],[fullhash:6]) — for output filenames and CSS ModuleslocalIdentName:[fullhash:6]/[hash:base64:6]/[contenthash:…]now work inlocalIdentName.[hash]inlocalIdentNamenow resolves to the local ident hash (matching css-loader) instead of the module hash;[modulehash]yields the module hash.[fullhash]/[chunkhash]and CSS[fullhash]/[hash]digests re-encode the untruncated hash (full entropy);[contenthash]re-encodes the stored hash and is rejected whenoptimization.realContentHashis enabled (it recomputes inoutput.hashDigest, which would silently drop the digest). Supported digests:hex,base64,base64url,base64safe,base26/32/36/49/52/58/62; an unknown digest throws. Placeholder-kind detection is centralized behind an exportedgetPresentKinds(reused byRuntimePlugin/SourceMapDevToolPlugin).What kind of change does this PR introduce?
feat (also fixes the two bugs in #21141).
Did you add tests for your changes?
Yes —
test/TemplatedPathPlugin.unittest.js,test/nonNumericOnlyHash.unittest.js,test/configCases/hash-length/digest/, andtest/configCases/css/local-ident-name/.Does this PR introduce a breaking change?
Yes, for experimental CSS:
[hash]inlocalIdentNamechanges from the module hash to the local ident hash — migration: use[modulehash]for the previous behavior. Also, an unknown inline digest token now errors instead of being silently ignored.If relevant, what needs to be documented once your changes are merged or what have you already documented?
Documented in webpack/docs.webpack.js.org (same branch):
configuration/output.mdxandconfiguration/module.mdx— inline digest/length,[hash]/[fullhash]= local ident hash, the new[modulehash], and thathashDigestLengthis the lever for content-hash entropy.Use of AI
Yes. I used AI (Claude Code) to research loader-utils' placeholder grammar, draft the implementation, tests and docs, and run the test suites; every change was directed and reviewed by me. This complies with the webpack AI policy.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Dqzs5d8if5LVWEEFp91KEA
Generated by Claude Code