Skip to content

feat: support optimization.inlineExports#20973

Merged
alexander-akait merged 17 commits into
mainfrom
inline-exports
May 27, 2026
Merged

feat: support optimization.inlineExports#20973
alexander-akait merged 17 commits into
mainfrom
inline-exports

Conversation

@hai-x

@hai-x hai-x commented May 17, 2026

Copy link
Copy Markdown
Member

Summary

What kind of change does this PR introduce?

Support optimization.inlineExports which is a new opt-in optimization that inlines ESM exports bound to small primitive constants (≤6-byte null / undefined / boolean / number / string) at every import site for better tree-shaking.

Once every import is replaced with the literal, the import dependency becomes inactive, the export turns unused, and DCE can drop the export — and, when the module is side-effect free, the module itself.

Did you add tests for your changes?

TODO

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?

Yes

Use of AI

Mostly, port from rspack by claude code.

@changeset-bot

changeset-bot Bot commented May 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 884ad5a

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

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

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 May 17, 2026

Copy link
Copy Markdown
Contributor

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

Install it locally:

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

Comment thread test/configCases/inline-exports/basic/constants.no-inline.js Fixed
Comment thread test/configCases/inline-exports/basic/index.js Fixed
@codspeed-hq

codspeed-hq Bot commented May 17, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 47.3%

⚡ 1 improved benchmark
❌ 7 regressed benchmarks
✅ 136 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 "asset-modules-resource", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 211.7 KB 1,197.2 KB -82.32%
Memory benchmark "asset-modules-source", scenario '{"name":"mode-development","mode":"development"}' 503.9 KB 1,646.9 KB -69.41%
Memory benchmark "css-modules", scenario '{"name":"mode-development","mode":"development"}' 530.2 KB 1,300.3 KB -59.23%
Memory benchmark "many-modules-esm", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 138.3 KB 288.6 KB -52.07%
Memory benchmark "cache-filesystem", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 697.8 KB 1,091.5 KB -36.08%
Memory benchmark "lodash", scenario '{"name":"mode-development","mode":"development"}' 2.8 MB 3.8 MB -27.36%
Memory benchmark "many-modules-esm", scenario '{"name":"mode-development","mode":"development"}' 839.9 KB 1,100.5 KB -23.68%
Memory benchmark "concatenate-modules", scenario '{"name":"mode-development","mode":"development"}' 1,234.9 KB 777.5 KB +58.83%

Tip

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


Comparing inline-exports (33baa38) with main (9c84d8e)

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.

@alexander-akait

Copy link
Copy Markdown
Member

I like this feature, we will bring this in the next minor release

Comment thread test/configCases/inner-graph/cross-module-pure-normal/index.js Fixed
@hai-x hai-x force-pushed the inline-exports branch from a84d002 to e0f79ef Compare May 23, 2026 20:01
Comment thread test/configCases/inline-exports/basic/index.js Fixed
Comment thread test/configCases/inline-exports/basic/index.js Fixed
@alexander-akait

Copy link
Copy Markdown
Member

@hai-x Feel free to make ready to review when you resolve merge conflicts, I like this improvement

@hai-x

hai-x commented May 25, 2026

Copy link
Copy Markdown
Member Author

@alexander-akait Yeah, it's almost ready, just dealing with the snapshot errors to ensure this optimization is correct.

@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.61538% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.71%. Comparing base (224f3ee) to head (884ad5a).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
lib/RuntimeTemplate.js 66.66% 3 Missing ⚠️
lib/optimize/ConcatenatedModule.js 89.28% 3 Missing ⚠️
...b/dependencies/HarmonyImportSpecifierDependency.js 93.10% 2 Missing ⚠️
...ncies/HarmonyEvaluatedImportSpecifierDependency.js 83.33% 1 Missing ⚠️
lib/dependencies/ImportMetaPlugin.js 87.50% 1 Missing ⚠️
lib/dependencies/ProvidedDependency.js 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #20973      +/-   ##
==========================================
+ Coverage   91.67%   91.71%   +0.04%     
==========================================
  Files         573      577       +4     
  Lines       59874    60307     +433     
  Branches    16159    16315     +156     
==========================================
+ Hits        54888    55313     +425     
- Misses       4986     4994       +8     
Flag Coverage Δ
integration 89.62% <95.38%> (+0.04%) ⬆️
test262 45.62% <76.54%> (+0.25%) ⬆️
unit 38.10% <23.45%> (+0.03%) ⬆️

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.

@hai-x hai-x marked this pull request as ready for review May 27, 2026 12:22
@alexander-akait

Copy link
Copy Markdown
Member

@hai-x let's skip some tests for globalThis and node@10

@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging inline-exports into main will be
98.97%
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.48%100%100%98.48%1576, 1872, 1879, 1887, 1909, 2805, 3230, 3894, 3923, 3976–3977, 3981, 3986, 4002–4003, 4017–4018, 4023–4024, 4501, 4527, 511, 516, 5335, 5367, 5384, 5400, 5416, 5431, 5456–5457, 5459, 5787, 5792, 5798, 5801, 5813, 5815, 5819, 5835, 5850, 5882, 5936, 5960, 6074, 730–731
   Compiler.js99.56%100%100%99.56%1135–1136, 1144
   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.40%100%100%97.40%258, 395, 418, 420, 424, 433–434
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js99%100%100%99%170–171, 187, 206, 280
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.20%100%100%98.20%383, 429
   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.81%100%100%98.81%422, 424, 428
   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.49%100%100%98.49%1302, 1307, 1367, 1381, 1443, 1452
   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%659
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js98.12%100%100%98.12%1212, 1215, 1232, 1249, 1496, 1530, 1546, 1633, 2257, 2262–2272, 569
   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.62%100%100%98.62%220, 224, 226, 419, 430, 891
   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%326
   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.30%100%100%99.30%1427–1429, 1437, 272, 275, 280, 284
   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%
   Fallbac

@@ -0,0 +1,3 @@
const INLINE_1 = 1;
import * as reexportedDestructingBarrelSideEffects from "./re-export.destructing-barrel-side-effects.js";
import * as constantsCjs from "./constants.cjs";
import * as constantsNoInline from "./constants.no-inline.js";
import { REMOVE_b as BRANCH_TRUE, REMOVE_FALSE as BRANCH_FALSE } from "./constants.js";
import { REMOVE_b as BRANCH_TRUE, REMOVE_FALSE as BRANCH_FALSE } from "./constants.js";

const fs = __non_webpack_require__("fs");
const path = __non_webpack_require__("path");
@hai-x

hai-x commented May 27, 2026

Copy link
Copy Markdown
Member Author

I want to add more test cases, please do not merge yet. I will finish those test cases today.

@alexander-akait alexander-akait merged commit 1ea4f72 into main May 27, 2026
59 of 61 checks passed
@alexander-akait alexander-akait deleted the inline-exports branch May 27, 2026 15:36
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