Skip to content

fix: hash inlined export literals at the dependency level - #22050

Merged
alexander-akait merged 4 commits into
mainfrom
fix/inline-exports-reexport-hash
Sep 12, 2026
Merged

alexander-akait merged 4 commits into
mainfrom
fix/inline-exports-reexport-hash

Conversation

@hai-x

@hai-x hai-x commented Sep 11, 2026 •

Copy link
Copy Markdown
Member

Summary

Follow-up to #22020. Refs #22019.

ChunkGraph hash only kept inlined HarmonyImportSpecifierDependency connections, so a re-exporter kept alive by its side effects still served a stale literal from its export getter after a cached rebuild.

HarmonyImportSpecifierDependency and HarmonyExportImportedSpecifierDependency now feed the inlined literal into updateHash themselves, which replaces the ChunkGraph special case and the ConstExportsPlugin refresh branch it needed.

cc @xiaoxiaojx

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes

Does this PR introduce a breaking change?

No

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a

Use of AI

Yes

Summary by CodeRabbit

  • Bug Fixes

    • Fixed stale cached values when exported constants change during watch mode.
    • Improved module graph tracking so inactive connections no longer affect rebuild results.
    • Ensured re-exported and imported values are correctly reflected when determining whether cached modules need updating.
  • Tests

    • Added coverage for dynamic imports, side effects, and updated inlined export values in watch mode.

@changeset-bot

changeset-bot Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 0500b33

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

@coderabbitai

coderabbitai Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 4a9818a5-1e52-4c4f-8ea9-edf52819c795

📥 Commits

Reviewing files that changed from the base of the PR and between 22f9041 and f3dfeb0.

⛔ Files ignored due to path filters (1)
  • types.d.ts is excluded by !types.d.ts
📒 Files selected for processing (7)
  • lib/ChunkGraph.js
  • lib/dependencies/HarmonyExportImportedSpecifierDependency.js
  • lib/dependencies/HarmonyImportSpecifierDependency.js
  • lib/optimize/ConstExportsPlugin.js
  • lib/optimize/InlineExports.js
  • test/watchCases/cache/inline-exports-value-change/0/index.js
  • test/watchCases/cache/inline-exports-value-change/0/reexport-side-effect.js

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Changes

Inline export hashing

Layer / File(s) Summary
Inline export hash contracts
lib/optimize/InlineExports.js, lib/dependencies/Harmony*SpecifierDependency.js
InlinedUsedName now hashes its rendered value and suffix. Applicable Harmony import and reexport dependencies include inline export data in dependency hashes.
Chunk graph inactive-connection hashing
lib/ChunkGraph.js
Single-runtime and multi-runtime hashing now skip inactive connections without inline-export special handling.
Inline export rebuild behavior and coverage
lib/optimize/ConstExportsPlugin.js, test/watchCases/cache/inline-exports-value-change/0/*
Const export inlining skips exports with existing used names. The watch case validates a side-effecting reexport after an inline value change.

Suggested reviewers: alexander-akait

Priority: ⬇️ Low

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 0500b

The cache rebuild path now updates inlined export values consistently, including side-effecting re-exports. No actionable merge risk remains.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title uses the required Conventional Commit form, uses the allowed type "fix", and accurately describes dependency-level hashing for inlined export literals. The branch prefix is not provided, so … Provide the branch name or its prefix to verify that it starts with "fix".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title uses the required Conventional Commit form, uses the allowed type "fix", and accurately describes dependency-level hashing for inlined export literals. The branch prefix is not provided, so the required type-prefix match cannot be verified.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added area: parser JavaScript parsing and dependency analysis (lib/javascript, lib/dependencies) area: optimization Tree-shaking, splitChunks, concatenation, ids (lib/optimize, lib/ids) labels Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

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

Install it locally:

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

@codecov

codecov Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.98%. Comparing base (3a69d29) to head (0500b33).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #22050      +/-   ##
==========================================
+ Coverage   94.97%   94.98%   +0.01%     
==========================================
  Files         726      726              
  Lines       97275    97285      +10     
  Branches    29629    29634       +5     
==========================================
+ Hits        92386    92406      +20     
+ Misses       4889     4879      -10     
Flag Coverage Δ
css-parsing 24.01% <0.00%> (-0.01%) ⬇️
html5lib 27.23% <7.69%> (-0.01%) ⬇️
integration 87.49% <100.00%> (+0.01%) ⬆️
syntax-equivalence 78.25% <ø> (ø)
test262 44.85% <97.43%> (+0.02%) ⬆️
unit 60.22% <12.82%> (-0.02%) ⬇️

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

☔ View full report in Codecov by Harness.
📢 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.

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Generated code size

Comparing 0500b33 merged into 3a69d29 against 3a69d29. Merging this pull request will not change the code webpack generates.

What moved Cases Assets Gzip Raw Case source
Changed, same case source 0 0 — — —
Changed, case source moved 0 0 — — —
New 0 0 — — —
Deleted 0 0 — — —
Unchanged — 7522 — — —

Changed, same case source is the row that is webpack's doing — those assets are built from byte-identical module source, so what moved is what webpack generates. Changed, case source moved is mostly a case this pull request edited: Case source is how many bytes of module source those cases gained, which is what their output delta has to be read against, and a bundle that grew by less than its case did is not a regression. New and Deleted are whole assets rather than deltas, so a pull request adding cases cannot bury a real change. Gzip decides — it is what a user downloads, and a re-encoding can cut raw bytes while costing wire bytes; raw is the tiebreak, and brotli and zstd are per asset below.

No asset changed size.

No runtime gained or lost a runtime module.

Built test/configCases with the defaults a user gets: 2112 case(s), 7522 asset(s), 87 emitted nothing.

@hai-x
hai-x force-pushed the fix/inline-exports-reexport-hash branch from 3e7dd39 to f3dfeb0 Compare September 11, 2026 11:22
@github-actions github-actions Bot added the area: types types.d.ts, JSDoc annotations, hand-maintained declarations label Sep 11, 2026
@codspeed

codspeed Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

Merging this PR will degrade performance by 5.43%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 4 improved benchmarks
❌ 4 regressed benchmarks
✅ 386 untouched benchmarks
⏩ 6 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Memory benchmark "asset-modules-source", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 484.1 KB 1,017.6 KB -52.42%
❌ Memory benchmark "no-exports-analysis", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 461.1 KB 902.6 KB -48.91%
❌ Memory benchmark "devtool-eval-source-map", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 1.2 MB 1.5 MB -24.06%
❌ Memory benchmark "many-modules-interop-runtime", scenario '{"name":"mode-production","mode":"production"}', measure 'exec' 16.2 KB 20.4 KB -20.32%
⚡ Memory benchmark "no-minimize", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 902.7 KB 462.5 KB +95.19%
⚡ Memory benchmark "common-libs", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 760.1 KB 563 KB +35.02%
⚡ Memory benchmark "asset-modules-source", scenario '{"name":"mode-production","mode":"production"}' 8.4 MB 6.3 MB +33.59%
⚡ Memory unit benchmark "js-parser-unit", source 'react.development.js' 740.1 KB 598.8 KB +23.59%

Tip

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


Comparing fix/inline-exports-reexport-hash (0500b33) with main (3a69d29)

Open in CodSpeed

Footnotes

  1. 6 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. ↩

@hai-x
hai-x marked this pull request as ready for review September 11, 2026 14:39
@hai-x
hai-x force-pushed the fix/inline-exports-reexport-hash branch from f3dfeb0 to 0500b33 Compare September 11, 2026 15:19
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging fix/inline-exports-reexport-hash into main will be
99.08%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.82%100%100%98.82%103
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.js100%100%100%100%
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/module-federation
   test.filter.js100%100%100%100%
examples/reexport-components
   test.filter.js100%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-emscripten
   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.js93.94%100%100%93.94%59, 62
   BannerPlugin.js100%100%100%100%
   Cache.js98.25%100%100%98.25%104
   CacheFacade.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%42
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CircularModulesPlugin.js99.35%100%100%99.35%244
   CleanPlugin.js97.81%100%100%97.81%111, 125, 128, 212, 232
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.62%100%100%98.62%1756, 2075, 2082, 2090, 2112, 2115, 3054, 3533–3534, 3566, 4155, 4159, 4258, 4279, 4406, 4445, 4452, 4505–4506, 4510, 4515, 4531–4532, 4546–4547, 4552–4553, 5076, 5102, 5943, 5960, 5978, 5994, 6009, 6034, 6037, 6401, 6404–6405, 6410, 6425, 6508, 6532, 6646, 836–837
   Compiler.js98.82%100%100%98.82%1113, 1150, 1153, 1333–1334, 1342, 844, 930, 971
   ConcatenationScope.js99.10%100%100%99.10%293
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js99.88%100%100%99.88%1557
   ContextModuleFactory.js95.66%100%100%95.66%230, 257, 276, 280–281, 289, 465, 486, 491, 532, 543, 545, 549, 552, 558–559
   ContextReplacementPlugin.js100%100%100%100%
   CopyPlugin.js99.79%100%100%99.79%160
   DefinePlugin.js99.14%100%100%99.14%1124, 197–198, 214, 233, 307
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.54%100%100%98.54%498, 545
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DotenvPlugin.js98.07%100%100%98.07%395, 443, 456–457
   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.js99.26%100%100%99.26%415, 431, 763, 860, 878, 922, 927
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.76%100%100%98.76%1340, 1343, 590–594, 596, 756
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.75%100%100%99.75%187, 285, 3947, 3962, 3986, 3989
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js95.64%100%100%95.64%119, 130, 147, 167, 171, 50, 52, 533, 538, 54, 545, 560, 563, 57
   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%
   LazyBarrel.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%1317, 1322, 1381, 1395, 1457, 1466
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.90%100%100%98.90%111, 113
   ModuleGraph.js99.78%100%100%99.78%1180
   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.js98.88%100%100%98.88%462, 542, 729, 794
   MultiStats.js100%100%100%100%
   MultiWatching.js93.75%100%100%93.75%37, 71
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js98.10%100%100%98.10%1044, 1047, 1066, 1083, 1353, 1387, 1403, 1861, 2157, 2162–2170, 2172, 29
   NormalModuleFactory.js98.01%100%100%98.01%1341, 1644, 1661, 1670, 1674, 1702, 1709, 1713, 1718, 1730, 1741, 1790, 1801, 1811, 1862–1864, 1871, 732, 744
   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.js99.80%100%100%99.80%694
   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.js95.45%100%100%95.45%314, 390, 399, 402, 415–416, 430, 448, 469–470, 493, 513–514, 550–551, 574, 587–588, 660, 673, 694, 713
   RuntimeTemplate.js99.65%100%100%99.65%367, 3802, 4464, 4476, 4481, 4483, 4488
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js97.25%100%100%97.25%229, 233, 235, 429, 440, 469, 572, 575–576, 899, 920, 923
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.48%100%100%99.48%366–367
   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%375
   cli.js98.63%100%100%98.63%10, 117, 547, 579, 629, 903
   index.js99.73%100%100%99.73%184
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js97.12%100%100%97.12%10, 274, 296, 298
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js98.15%100%100%98.15%338, 362, 365, 495, 57, 62
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
   WebManifestGenerator.js100%100%100%100%
   WebManifestParser.js100%100%100%1

@alexander-akait
alexander-akait merged commit cd0282c into main Sep 12, 2026
64 checks passed
@alexander-akait
alexander-akait deleted the fix/inline-exports-reexport-hash branch September 12, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: optimization Tree-shaking, splitChunks, concatenation, ids (lib/optimize, lib/ids) area: parser JavaScript parsing and dependency analysis (lib/javascript, lib/dependencies) area: types types.d.ts, JSDoc annotations, hand-maintained declarations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants