Skip to content

fix(cjs): disconnect unused side-effect-free reexport requires - #21651

Merged
alexander-akait merged 1 commit into
mainfrom
fix/cjs-unused-reexport-disconnect
Aug 9, 2026
Merged

alexander-akait merged 1 commit into
mainfrom
fix/cjs-unused-reexport-disconnect

Conversation

@xiaoxiaojx

@xiaoxiaojx xiaoxiaojx commented Aug 9, 2026 •

Copy link
Copy Markdown
Member

Summary

Unused named CJS reexports (exports.x = require(...) / unused getters) kept the target module in the graph even when side-effect-free; deactivate those edges like evaluation-only requires, while keeping whole-module assigns and missing targets (e.g. IgnorePlugin) alive.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes — test/configCases/cjs-tree-shaking/unused-*, updated side-effect-free-*-unused-export-require, and test/configCases/ignore/unused-getter-reexport.

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 assisted implementation of getCondition on CommonJsExportRequireDependency, regression fixtures, and review of edge cases (IgnorePlugin / missing connection).

Made with Cursor

Summary by CodeRabbit

  • New Features
    • Improved CommonJS tree-shaking to remove unused re-exports from side-effect-free modules.
    • Preserved required execution for unused re-exports that may have side effects.
    • Added support for safely handling unused nested, getter-based, and package-based re-export patterns.
  • Bug Fixes
    • Prevented cyclic unused re-exports from causing processing issues.
  • Tests
    • Added coverage for multiple CommonJS re-export forms, side-effect behavior, module concatenation, and ignored modules.

Deactivate CommonJsExportRequireDependency when a named reexport is
unused and either a getter or an eager require of a side-effect-free
module, while keeping whole-module assigns and missing targets alive.
@changeset-bot

changeset-bot Bot commented Aug 9, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c1d4459

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 changesets to release 1 package
Name Type
webpack Patch

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 Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

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

Install it locally:

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

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging fix/cjs-unused-reexport-disconnect into main will be
99.29%
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.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.13%100%100%99.13%214, 234
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.42%100%100%98.42%1648, 1967, 1974, 1982, 2004, 2007, 2946, 3425–3426, 3458, 4162, 4192, 4245–4246, 4250, 4255, 4271–4272, 4286–4287, 4292–4293, 4773, 4799, 527, 532, 5607, 5639, 5656, 5672, 5688, 5703, 5728–5729, 5731, 6061, 6066, 6072, 6075, 6082, 6094, 6096, 6100, 6116, 6131, 6163, 6217, 6241, 6356, 778–779
   Compiler.js99.56%100%100%99.56%1159–1160, 1168
   ConcatenationScope.js99.12%100%100%99.12%300
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js99.88%100%100%99.88%1461
   ContextModuleFactory.js97.20%100%100%97.20%266, 435, 456, 461, 501, 512, 514, 518, 527–528
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js99.08%100%100%99.08%1080, 176–177, 193, 212, 286
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.51%100%100%98.51%480, 527
   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.67%100%100%98.67%1216, 1219, 515–519, 521, 667
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.16%100%100%99.16%1267, 1269–1274, 1281, 1284, 182, 2502–2503, 2506, 2517, 2528, 2539, 280, 3976, 3991, 4015
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.21%100%100%98.21%448, 457, 460, 464, 476
   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.51%100%100%98.51%1303, 1308, 1368, 1382, 1444, 1453
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.90%100%100%98.90%111, 113
   ModuleGraph.js99.78%100%100%99.78%1170
   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.72%100%100%99.72%716
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.98%100%100%97.98%1020, 1023, 1040, 1057, 1305, 1339, 1355, 1803, 2100, 2105–2115, 34
   NormalModuleFactory.js98.72%100%100%98.72%1123, 1391, 1402, 1412, 1463–1465, 1472, 526, 538
   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%691
   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.63%100%100%98.63%220, 224, 226, 420, 431, 890
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.47%100%100%99.47%352–353
   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.73%100%100%99.73%184
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js97.10%100%100%97.10%10, 263, 285, 287
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.95%100%100%97.95%295, 319, 322, 42, 452, 47
   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%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
   isGeneratorLowered.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.js92%100%100%92%34, 43
   MemoryWithGcCachePlugin.js93.42%100%100%93.42%108, 122–123, 132, 90
   PackFileCacheStrategy.js96.52%100%100%96.52%1310, 1410, 1414, 1476, 1712, 1796, 1819, 1851, 675, 694, 704–706, 708, 724–725, 730, 733, 735, 740, 745, 770, 776, 810, 816, 822, 827, 838, 847, 852–853, 855, 872, 878–879, 881
   ResolverCachePlugin.js100%100%100%100%
   

@codecov

codecov Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.26%. Comparing base (267ef49) to head (c1d4459).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #21651   +/-   ##
=======================================
  Coverage   94.26%   94.26%           
=======================================
  Files         628      628           
  Lines       80106    80178   +72     
  Branches    23711    23734   +23     
=======================================
+ Hits        75512    75580   +68     
- Misses       4594     4598    +4     
Flag Coverage Δ
css-parsing 25.87% <0.00%> (-0.03%) ⬇️
html5lib 27.31% <0.00%> (-0.02%) ⬇️
integration 88.82% <100.00%> (-0.04%) ⬇️
test262 49.07% <0.00%> (-0.02%) ⬇️
unit 52.14% <0.00%> (+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.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 46f82a5a-c491-499f-9f7e-91462d810ea9

📥 Commits

Reviewing files that changed from the base of the PR and between c63ac95 and c1d4459.

⛔ Files ignored due to path filters (2)
  • test/configCases/cjs-tree-shaking/unused-reexport-package-sideEffects-drop/node_modules/sef-pkg/index.js is excluded by !**/node_modules/**
  • test/configCases/cjs-tree-shaking/unused-reexport-package-sideEffects-drop/node_modules/sef-pkg/package.json is excluded by !**/node_modules/**
📒 Files selected for processing (27)
  • .changeset/040-drop-unused-cjs-requires.md
  • lib/dependencies/CommonJsExportRequireDependency.js
  • test/configCases/cjs-tree-shaking/side-effect-free-cyclic-unused-export-require/index.js
  • test/configCases/cjs-tree-shaking/side-effect-free-unused-export-require/index.js
  • test/configCases/cjs-tree-shaking/unused-eager-reexport-keeps-effect/effect.cjs
  • test/configCases/cjs-tree-shaking/unused-eager-reexport-keeps-effect/index.js
  • test/configCases/cjs-tree-shaking/unused-eager-reexport-keeps-effect/lib.cjs
  • test/configCases/cjs-tree-shaking/unused-eager-reexport-keeps-effect/webpack.config.js
  • test/configCases/cjs-tree-shaking/unused-getter-reexport-drop/heavy.cjs
  • test/configCases/cjs-tree-shaking/unused-getter-reexport-drop/index.js
  • test/configCases/cjs-tree-shaking/unused-getter-reexport-drop/lib.cjs
  • test/configCases/cjs-tree-shaking/unused-getter-reexport-drop/webpack.config.js
  • test/configCases/cjs-tree-shaking/unused-reexport-concatenated-drop/index.js
  • test/configCases/cjs-tree-shaking/unused-reexport-concatenated-drop/lib.cjs
  • test/configCases/cjs-tree-shaking/unused-reexport-concatenated-drop/sef.cjs
  • test/configCases/cjs-tree-shaking/unused-reexport-concatenated-drop/webpack.config.js
  • test/configCases/cjs-tree-shaking/unused-reexport-forms-drop/index.js
  • test/configCases/cjs-tree-shaking/unused-reexport-forms-drop/lib.cjs
  • test/configCases/cjs-tree-shaking/unused-reexport-forms-drop/sef.cjs
  • test/configCases/cjs-tree-shaking/unused-reexport-forms-drop/webpack.config.js
  • test/configCases/cjs-tree-shaking/unused-reexport-package-sideEffects-drop/index.js
  • test/configCases/cjs-tree-shaking/unused-reexport-package-sideEffects-drop/lib.cjs
  • test/configCases/cjs-tree-shaking/unused-reexport-package-sideEffects-drop/webpack.config.js
  • test/configCases/ignore/unused-getter-reexport/folder-b/ignored-module.js
  • test/configCases/ignore/unused-getter-reexport/folder-b/lib.cjs
  • test/configCases/ignore/unused-getter-reexport/index.js
  • test/configCases/ignore/unused-getter-reexport/webpack.config.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • webpack/schema-utils (auto-detected)
  • webpack/tapable (auto-detected)

Walkthrough

CommonJsExportRequireDependency now evaluates module connection state for named CommonJS reexports. Unused reexports are replaced with an unused marker when the target is side-effect-free. Used exports, getters, eager side-effectful modules, missing-module behavior, and cyclic dependencies remain covered by configuration tests. The changeset documents removal of unused side-effect-free CommonJS reexports.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes disconnecting unused side-effect-free CommonJS reexport requires, which is the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cjs-unused-reexport-disconnect

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

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Generated code size

Comparing c1d4459 against c63ac95. Merging this PR will change the code webpack generates.

Changed New Deleted Unchanged Raw change
Cases 2 6 0 1502 🔴 ↑ +12.63 KiB
Assets 2 6 0 5899 🔴 ↑ +12.63 KiB
Runtimes 0 1 0 1858 —
8 asset(s) changed size
Asset Before After Change Gzip (9) Brotli (11) Zstd (19)
➕ cjs-tree-shaking/unused-reexport-forms-drop bundle0.js — 2.30 KiB +2.30 KiB (new) new new new
➕ cjs-tree-shaking/unused-eager-reexport-keeps-effect bundle0.js — 2.29 KiB +2.29 KiB (new) new new new
➕ ignore/unused-getter-reexport bundle0.js — 2.22 KiB +2.22 KiB (new) new new new
➕ cjs-tree-shaking/unused-reexport-package-sideEffects-drop bundle0.js — 2.21 KiB +2.21 KiB (new) new new new
➕ cjs-tree-shaking/unused-reexport-concatenated-drop bundle0.js — 2.10 KiB +2.10 KiB (new) new new new
➕ cjs-tree-shaking/unused-getter-reexport-drop bundle0.js — 2.08 KiB +2.08 KiB (new) new new new
🟢 ↓ cjs-tree-shaking/side-effect-free-unused-export-require bundle0.js 2.70 KiB 2.34 KiB -364 B (-13.16%) -9.50% -9.48% -8.77%
🟢 ↓ cjs-tree-shaking/side-effect-free-cyclic-unused-export-require bundle0.js 2.65 KiB 2.42 KiB -236 B (-8.71%) -12.12% -8.68% -12.04%
1 runtime(s) changed which runtime modules they carry
Runtime Modules Added Removed
➕ cjs-tree-shaking/unused-reexport-concatenated-drop main 0 → 1 concatenation wrap —

Built test/configCases with the defaults a user gets: 1510 case(s), 5907 asset(s), 35 emitted nothing.

@codspeed

codspeed Bot commented Aug 9, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 19.35%

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

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 218 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Memory benchmark "devtool-eval", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 509.3 KB 944.7 KB -46.09%
⚡ Memory benchmark "many-modules-esm", scenario '{"name":"mode-production","mode":"production"}' 10.9 MB 9 MB +20.66%

Tip

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


Comparing fix/cjs-unused-reexport-disconnect (c1d4459) with main (c63ac95)

Open in CodSpeed

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