Skip to content

test: cover all hash placeholders across js/css/html/asset outputs with and without realContentHash#21009

Merged
alexander-akait merged 3 commits into
mainfrom
claude/add-hash-placeholder-tests-GgfdG
May 21, 2026
Merged

test: cover all hash placeholders across js/css/html/asset outputs with and without realContentHash#21009
alexander-akait merged 3 commits into
mainfrom
claude/add-hash-placeholder-tests-GgfdG

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Adds test/configCases/contenthash/hash-placeholders/ to exercise
[fullhash]/[chunkhash]/[contenthash] across filename, chunkFilename,
cssFilename, cssChunkFilename, htmlFilename, htmlChunkFilename, and
assetModuleFilename, with optimization.realContentHash toggled on and
off. Verifies that emitted filenames have their placeholders resolved,
that the HTML's / URLs and the CSS's url() references match
the actual emitted asset filenames, and that the main bundle's chunk
URL helper points at real on-disk chunks — the html-webpack-plugin#1814
invariant.

…th and without realContentHash

Adds test/configCases/contenthash/hash-placeholders/ to exercise
[fullhash]/[chunkhash]/[contenthash] across filename, chunkFilename,
cssFilename, cssChunkFilename, htmlFilename, htmlChunkFilename, and
assetModuleFilename, with optimization.realContentHash toggled on and
off. Verifies that emitted filenames have their placeholders resolved,
that the HTML's <img>/<link> URLs and the CSS's url() references match
the actual emitted asset filenames, and that the main bundle's chunk
URL helper points at real on-disk chunks — the html-webpack-plugin#1814
invariant.
Copilot AI review requested due to automatic review settings May 21, 2026 14:30
@changeset-bot

changeset-bot Bot commented May 21, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a00ae0c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (b3893ec).

Install it locally:

  • npm
npm i -D webpack@https://pkg.pr.new/webpack@b3893ec
  • yarn
yarn add -D webpack@https://pkg.pr.new/webpack@b3893ec
  • pnpm
pnpm add -D webpack@https://pkg.pr.new/webpack@b3893ec

@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.63%. Comparing base (6c5f2f8) to head (a00ae0c).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21009      +/-   ##
==========================================
+ Coverage   91.62%   91.63%   +0.01%     
==========================================
  Files         573      573              
  Lines       59232    59277      +45     
  Branches    15995    16012      +17     
==========================================
+ Hits        54272    54321      +49     
+ Misses       4960     4956       -4     
Flag Coverage Δ
integration 89.65% <ø> (+0.01%) ⬆️
test262 45.36% <ø> (-0.02%) ⬇️
unit 37.85% <ø> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new configCases test scenario to ensure webpack resolves hash placeholders consistently across JS/CSS/HTML/asset outputs, and that rewritten URLs in extracted HTML/CSS match the actually emitted filenames (including with optimization.realContentHash on/off), covering the html-webpack-plugin#1814 invariant.

Changes:

  • Add a new multi-config test case under test/configCases/contenthash/hash-placeholders/ that emits JS/CSS/HTML/assets into per-config subfolders and toggles optimization.realContentHash.
  • Validate on-disk outputs: all expected assets exist, no unresolved placeholder tokens remain, and HTML/CSS URL rewrites point at real emitted files.
  • Add minimal fixtures (JS entry + async chunks, HTML/CSS sources, and referenced PNG assets).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/configCases/contenthash/hash-placeholders/webpack.config.js Defines 6 config variants covering [contenthash], [chunkhash], [fullhash] for JS/CSS/HTML outputs and toggles realContentHash.
test/configCases/contenthash/hash-placeholders/test.config.js Asserts emitted filenames/URLs are consistent and verifies chunk URL resolution logic.
test/configCases/contenthash/hash-placeholders/index.js Entry tests that dynamically import an async JS chunk and an async CSS chunk.
test/configCases/contenthash/hash-placeholders/style.css CSS that references an image via url() to validate URL rewriting.
test/configCases/contenthash/hash-placeholders/page.html HTML referencing image and icon assets to validate URL rewriting.
test/configCases/contenthash/hash-placeholders/async.js Async JS module fixture.
test/configCases/contenthash/hash-placeholders/async.css Async CSS module fixture.
test/configCases/contenthash/hash-placeholders/bg.png Asset fixture referenced by HTML and CSS.
test/configCases/contenthash/hash-placeholders/icon.png Asset fixture referenced by HTML.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +155 to +157
const uHelperMatch = bundleContent.match(
/\.u\s*=\s*\(chunkId\)\s*=>\s*\{[\s\S]*?return\s+"[^"]+"\s*\+\s*chunkId\s*\+\s*"\."\s*\+\s*([\s\S]*?)\s*\+\s*"\.js";/
);
Comment on lines +137 to +140
// to lazy-load a chunk. Pull every hash literal that lives
// inside a `__webpack_require__.{u,k}` (JS) / `__webpack_require__.f.css`
// (CSS) helper, splice it into the templated filename, and
// confirm the result is a file that exists.
@codspeed-hq

codspeed-hq Bot commented May 21, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 52.6%

⚡ 7 improved benchmarks
❌ 2 regressed benchmarks
✅ 135 untouched benchmarks
⏩ 72 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "json-modules", scenario '{"name":"mode-development","mode":"development"}' 841.4 KB 578.6 KB +45.41%
Memory benchmark "json-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 1,358.9 KB 807.1 KB +68.37%
Memory benchmark "concatenate-modules", scenario '{"name":"mode-development","mode":"development"}' 1,106.9 KB 783.2 KB +41.34%
Memory benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 521.7 KB 229 KB ×2.3
Memory benchmark "concatenate-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 489 KB 163.1 KB ×3
Memory benchmark "side-effects-reexport", scenario '{"name":"mode-development","mode":"development"}' 4.8 MB 3.8 MB +25.99%
Memory benchmark "many-modules-commonjs", scenario '{"name":"mode-development","mode":"development"}' 847.5 KB 1,102.2 KB -23.1%
Memory benchmark "asset-modules-resource", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 1,197 KB 210.9 KB ×5.7
Memory benchmark "cache-filesystem", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 292.5 KB 846.8 KB -65.46%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing claude/add-hash-placeholder-tests-GgfdG (a00ae0c) with main (9e8717e)

Open in CodSpeed

Footnotes

  1. 72 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

…function-form chunk helpers

Addresses Copilot review feedback on PR #21009:
- Adds the CSS chunk URL helper check (__webpack_require__.k) that the
  comment block promised but the implementation was missing.
- Loosens the chunk-URL helper regex to match both arrow and
  `function`-syntax forms, since `output.environment.arrowFunction: false`
  switches webpack from one to the other; the same applies to
  __webpack_require__.h on [fullhash] variants.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comment thread test/configCases/contenthash/hash-placeholders/test.config.js Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 21, 2026 16:52
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging claude/add-hash-placeholder-tests-GgfdG into main will be
98.96%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.77%100%100%98.77%91
examples
   build-common.js100%100%100%100%
   buildAll.js100%100%100%100%
   examples.js100%100%100%100%
   template-common.js98.21%100%100%98.21%72
examples/custom-javascript-parser
   test.filter.js100%100%100%100%
examples/custom-javascript-parser/internals
   acorn-parse.js100%100%100%100%
   meriyah-parse.js100%100%100%100%
   oxc-parse.js91.30%100%100%91.30%140, 142–143, 145, 147, 153–154, 161, 168, 90
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/typescript
   test.filter.js100%100%100%100%
examples/typescript-non-erasable
   test.filter.js50%100%100%50%5
examples/virtual-modules
   test.filter.js100%100%100%100%
examples/wasm-bindgen-esm
   test.filter.js100%100%100%100%
examples/wasm-complex
   test.filter.js100%100%100%100%
examples/wasm-simple
   test.filter.js100%100%100%100%
examples/wasm-simple-source-phase
   test.filter.js100%100%100%100%
lib
   APIPlugin.js100%100%100%100%
   AsyncDependenciesBlock.js100%100%100%100%
   AutomaticPrefetchPlugin.js100%100%100%100%
   BannerPlugin.js100%100%100%100%
   Cache.js98.21%100%100%98.21%101
   CacheFacade.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%39
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CleanPlugin.js99.15%100%100%99.15%206, 226
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.45%100%100%98.45%1572, 1868, 1875, 1883, 1905, 2801, 3226, 3888, 3917, 3970–3971, 3975, 3980, 3996–3997, 4011–4012, 4017–4018, 4495, 4521, 511, 516, 5229, 5261, 5278, 5294, 5310, 5325, 5350–5351, 5353, 5681, 5686, 5692, 5695, 5707, 5709, 5713, 5729, 5744, 5776, 5830, 5854, 5968, 730–731
   Compiler.js99.55%100%100%99.55%1116–1117, 1125
   ConcatenationScope.js98.59%100%100%98.59%189
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js100%100%100%100%
   ContextModuleFactory.js97.75%100%100%97.75%258, 393, 418, 443, 447, 458
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js98.92%100%100%98.92%158–159, 175, 194, 268
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.20%100%100%98.20%379, 425
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DotenvPlugin.js98.41%100%100%98.41%378, 391–392
   DynamicEntryPlugin.js100%100%100%100%
   EntryOptionPlugin.js100%100%100%100%
   EntryPlugin.js100%100%100%100%
   Entrypoint.js100%100%100%100%
   EnvironmentPlugin.js97.14%100%100%97.14%49
   ErrorHelpers.js100%100%100%100%
   EvalDevToolModulePlugin.js100%100%100%100%
   EvalSourceMapDevToolPlugin.js100%100%100%100%
   ExportsInfo.js100%100%100%100%
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.97%100%100%98.97%425–429, 577
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.50%100%100%99.50%182, 2252–2253, 2256, 2267, 2278, 2289, 278, 3694, 3709, 3733
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.74%100%100%98.74%399, 401, 405
   FlagDependencyUsagePlugin.js100%100%100%100%
   FlagEntryExportAsUsedPlugin.js100%100%100%100%
   Generator.js100%100%100%100%
   HotModuleReplacementPlugin.js100%100%100%100%
   HotUpdateChunk.js100%100%100%100%
   IgnorePlugin.js100%100%100%100%
   IgnoreWarningsPlugin.js100%100%100%100%
   InitFragment.js100%100%100%100%
   JavascriptMetaInfoPlugin.js100%100%100%100%
   LibraryTemplatePlugin.js100%100%100%100%
   LoaderOptionsPlugin.js100%100%100%100%
   LoaderTargetPlugin.js100%100%100%100%
   MainTemplate.js100%100%100%100%
   ManifestPlugin.js100%100%100%100%
   Module.js98.50%100%100%98.50%1305, 1310, 1371, 1385, 1447, 1456
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%106, 108
   ModuleGraph.js99.73%100%100%99.73%1004
   ModuleGraphConnection.js100%100%100%100%
   ModuleInfoHeaderPlugin.js100%100%100%100%
   ModuleNotFoundError.js100%100%100%100%
   ModuleProfile.js100%100%100%100%
   ModuleSourceTypeConstants.js100%100%100%100%
   ModuleTemplate.js100%100%100%100%
   ModuleTypeConstants.js100%100%100%100%
   MultiCompiler.js99.69%100%100%99.69%645
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.83%100%100%97.83%1072, 1106, 1122, 1209, 1834, 1839–1849, 794, 797, 814, 831
   NormalModuleFactory.js99.47%100%100%99.47%1083, 1392, 486, 498
   NormalModuleReplacementPlugin.js100%100%100%100%
   NullFactory.js100%100%100%100%
   OptimizationStages.js100%100%100%100%
   OptionsApply.js100%100%100%100%
   Parser.js100%100%100%100%
   PlatformPlugin.js100%100%100%100%
   PrefetchPlugin.js100%100%100%100%
   ProgressPlugin.js98.85%100%100%98.85%519–520, 525, 527, 591
   ProvidePlugin.js100%100%100%100%
   RawModule.js100%100%100%100%
   RecordIdsPlugin.js100%100%100%100%
   RequestShortener.js100%100%100%100%
   ResolverFactory.js100%100%100%100%
   RuntimeGlobals.js100%100%100%100%
   RuntimeModule.js100%100%100%100%
   RuntimePlugin.js100%100%100%100%
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js98.59%100%100%98.59%218, 222, 224, 398, 409, 811
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js98.86%100%100%98.86%136–137
   UseStrictPlugin.js100%100%100%100%
   WarnCaseSensitiveModulesPlugin.js100%100%100%100%
   WarnDeprecatedOptionPlugin.js100%100%100%100%
   WarnNoModeSetPlugin.js100%100%100%100%
   WatchIgnorePlugin.js100%100%100%100%
   Watching.js100%100%100%100%
   WebpackError.js100%100%100%100%
   WebpackIsIncludedPlugin.js100%100%100%100%
   WebpackOptionsApply.js100%100%100%100%
   WebpackOptionsDefaulter.js100%100%100%100%
   buildChunkGraph.js99.87%100%100%99.87%325
   cli.js98.46%100%100%98.46%10, 119, 471, 503, 545, 815
   index.js99.72%100%100%99.72%165
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js96.33%100%100%96.33%10, 198, 220, 222
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModulesPlugin.js97.32%100%100%97.32%283, 307, 310, 36, 362, 41
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%71, 83, 91
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%106, 113–114, 122, 89
   PackFileCacheStrategy.js96.40%100%100%96.40%1250, 1350, 1354, 1416, 628, 647, 657–659, 661, 677–678, 683, 686, 688, 693, 698, 722, 728, 762, 768, 774, 779, 790, 799, 804–805, 807, 824, 830–831, 833
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config
   browserslistTargetHandler.js100%100%100%100%
   defaults.js99.29%100%100%99.29%1411–1413, 1421, 271, 274, 279, 283
   normalization.js99%100%100%99%191–192, 258, 273
   target.js100%100%100%100%
lib/container
   ContainerEntryDependency.js100%100%100%100%
   ContainerEntryModule.js100%100%100%100%
   ContainerEntryModuleFactory.js100%100%100%100%
   ContainerExposedDependency.js100%100%100%100%
   ContainerPlugin.js100%100%100%100%
   ContainerReferencePlugin.js100%100%100%100%
   FallbackDependency.js100%100%100%100%
   FallbackItemDependency.js100%100%100%100%
   

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comment on lines +44 to +47
htmlFilename: `cfg${i}/[name].${htmlPlaceholder}.html`,
htmlChunkFilename: `cfg${i}/[name].${htmlPlaceholder}.html`,
assetModuleFilename: `cfg${i}/[name].[contenthash][ext]`
},
@alexander-akait alexander-akait merged commit b3893ec into main May 21, 2026
62 checks passed
@alexander-akait alexander-akait deleted the claude/add-hash-placeholder-tests-GgfdG branch May 21, 2026 19:29
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.

2 participants