Skip to content

fix: don't cache incomplete exports of lazy-barrel-deferred re-exports#21322

Closed
alexander-akait wants to merge 1 commit into
mainfrom
claude/webpack-issue-21318-tr4k63
Closed

fix: don't cache incomplete exports of lazy-barrel-deferred re-exports#21322
alexander-akait wants to merge 1 commit into
mainfrom
claude/webpack-issue-21318-tr4k63

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Summary

Fixes #21318. A side-effect-free barrel whose re-export target is deferred by the lazy barrel (e.g. mobx-react's export * from "mobx-react-lite") reports no exports for that dependency, so FlagDependencyExportsPlugin flagged the module cacheable and persisted a closed export set omitting those names. A later build that imports one of them (typical with lazyCompilation where an entry activates afterwards) restored the stale provided exports from the filesystem cache instead of recomputing, and reported the name as missing (export 'X' ... was not found). A resolved re-export already makes the module non-cacheable; this treats a lazy-deferred dependency the same way.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes — test/PersistentCaching.test.js (two filesystem-cache runs where the deferred star re-export's name is imported only on the second run). It fails on the old code and passes with the fix.

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

AI was used to help investigate the regression and draft the fix and test; the change and test were reviewed and verified locally.


Generated by Claude Code

A side-effect-free barrel whose re-export target is deferred by the lazy
barrel reports no exports for that dependency, so the module was flagged
cacheable and persisted with a closed export set omitting those names. On
a later build that imports one of them, the stale provided exports were
restored from the persistent cache and the name was reported as missing.
Treat a lazy-deferred dependency as non-cacheable, matching a resolved
re-export.

Closes #21318
Copilot AI review requested due to automatic review settings July 1, 2026 16:04
@changeset-bot

changeset-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5c72600

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
webpack Patch

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

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

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

Install it locally:

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

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging claude/webpack-issue-21318-tr4k63 into main will be
99.36%
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/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.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%
   CircularModulesPlugin.js98.81%100%100%98.81%136
   CleanPlugin.js99.12%100%100%99.12%207, 227
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.43%100%100%98.43%1641, 1960, 1967, 1975, 1997, 2000, 2939, 3418–3419, 3451, 4117, 4147, 4200–4201, 4205, 4210, 4226–4227, 4241–4242, 4247–4248, 4725, 4751, 526, 531, 5559, 5591, 5608, 5624, 5640, 5655, 5680–5681, 5683, 6011, 6016, 6022, 6025, 6037, 6039, 6043, 6059, 6074, 6106, 6160, 6184, 6298, 777–778
   Compiler.js99.56%100%100%99.56%1147–1148, 1156
   ConcatenationScope.js98.65%100%100%98.65%195
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js100%100%100%100%
   ContextModuleFactory.js97.40%100%100%97.40%258, 395, 418, 420, 424, 433–434
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js98.99%100%100%98.99%172–173, 189, 208, 282
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.51%100%100%98.51%479, 525
   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.55%100%100%98.55%1100, 1103, 502–506, 508, 654
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.52%100%100%99.52%182, 2382–2383, 2386, 2397, 2408, 2419, 280, 3823, 3838, 3862
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.43%100%100%98.43%419, 428, 430, 434
   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%1285, 1290, 1350, 1364, 1426, 1435
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%106, 108
   ModuleGraph.js99.73%100%100%99.73%1005
   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%661
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.89%100%100%97.89%1227, 1230, 1247, 1264, 1511, 1545, 1561, 1648, 2004, 2303, 2308–2318, 419, 423, 577
   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%527–528, 533, 535, 599
   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.62%100%100%98.62%220, 224, 226, 419, 430, 889
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.43%100%100%99.43%308–309
   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%371
   cli.js98.63%100%100%98.63%10, 119, 549, 581, 631, 905
   index.js99.72%100%100%99.72%184
   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%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.33%100%100%97.33%282, 306, 309, 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/bun
   BunTargetPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%75, 87, 95
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%107, 114–115, 123, 90
   PackFileCacheStrategy.js96.40%100%100%96.40%1251, 1351, 1355, 1417, 628, 647, 657–659, 661, 677–678, 683, 686, 688, 693, 698, 723, 729, 763, 769, 775, 780, 791, 800, 805–806, 808, 825, 831–832, 834
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config
   browserslistTargetHandler.js100%100%100%100%
   defaults.js99.33%100%100%99.33%1468–1470, 1478, 274,

@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.44%. Comparing base (676f564) to head (5c72600).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21322      +/-   ##
==========================================
- Coverage   92.45%   92.44%   -0.01%     
==========================================
  Files         590      594       +4     
  Lines       65123    65213      +90     
  Branches    18135    18144       +9     
==========================================
+ Hits        60209    60288      +79     
- Misses       4914     4925      +11     
Flag Coverage Δ
css-parsing 28.61% <33.33%> (+<0.01%) ⬆️
html5lib 28.22% <33.33%> (-2.92%) ⬇️
integration 88.89% <100.00%> (+0.63%) ⬆️
test262 45.59% <33.33%> (?)
unit 43.09% <33.33%> (+<0.01%) ⬆️

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.

@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 24.51%

⚠️ 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

⚡ 2 improved benchmarks
❌ 3 regressed benchmarks
✅ 139 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "wasm-modules-async", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 245.6 KB 1,035.5 KB -76.29%
Memory benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 384.4 KB 1,194.7 KB -67.83%
Memory benchmark "asset-modules-bytes", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 325.5 KB 858.9 KB -62.1%
Memory benchmark "side-effects-reexport", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 859.3 KB 132.8 KB ×6.5
Memory benchmark "many-modules-esm", scenario '{"name":"mode-production","mode":"production"}' 9.7 MB 7.4 MB +31.02%

Tip

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


Comparing claude/webpack-issue-21318-tr4k63 (5c72600) with main (e848598)

Open in CodSpeed

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

Fixes a persistent-filesystem-cache correctness issue where lazy-barrel deferred export * re-exports could be stored with an incomplete “provided exports” set, causing later compilations (e.g. when additional entries activate) to incorrectly report missing exports after restoring from cache.

Changes:

  • Mark modules as non-cacheable for provided-exports caching when encountering a lazy-barrel deferred dependency in FlagDependencyExportsPlugin.
  • Add a regression test that performs two filesystem-cache runs where a star re-exported name is imported only on the second run.
  • Add a changeset describing the patch-level fix.

Reviewed changes

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

File Description
lib/FlagDependencyExportsPlugin.js Disables caching of provided-exports data when a dependency is currently deferred by the lazy-barrel optimization.
test/PersistentCaching.test.js Adds an integration-style regression test covering restore-from-cache behavior across two builds.
.changeset/lazy-barrel-persistent-cache-exports.md Records the user-facing patch note for the fix.

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

Comment on lines +151 to +153
// lazy barrel deferred this re-export: its target is not built, so
// the provided exports are incomplete and must not be cached
if ("isLazy" in dep && dep.isLazy()) {
Comment on lines +309 to +313
// A side-effect-free barrel with a local export and a star re-export whose
// target is unused: the star stays deferred, so the barrel is cacheable and
// gets persisted as a closed export set omitting the star's exports. A later
// build that imports one of those names must recompute, not restore the stale
// exports and report the name as missing.

Copy link
Copy Markdown
Member Author

Closing in favour of #21326, which fixes the same root cause (FlagDependencyExportsPlugin keying the provided-exports cache on buildInfo.hash only, so a barrel is cached while a re-export target is still deferred) more completely.

#21326 keeps the cache working by folding the deferred-target set into the cache key, whereas this PR simply marks such barrels non-cacheable — the smaller change, but it drops the cache for those modules. Since #21326 is from the lazy-barrel author and preserves the cache, it's the better fix. Leaving the minimal "treat a lazy-deferred dependency as non-cacheable" approach here as a reference in case a smaller patch is ever preferred.


Generated by Claude Code

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.

Lazy compilation + FS cache = incorrect export X (imported as X) was not found in ...

2 participants