Skip to content

fix(library): aggregate exports from all entry modules (fixes #15936)#20447

Open
vvinit594 wants to merge 1 commit intowebpack:mainfrom
vvinit594:fix/15936-library-multiple-entry-exports
Open

fix(library): aggregate exports from all entry modules (fixes #15936)#20447
vvinit594 wants to merge 1 commit intowebpack:mainfrom
vvinit594:fix/15936-library-multiple-entry-exports

Conversation

@vvinit594
Copy link

Pull request body for #15936 (copy into GitHub when opening the PR)

What does this PR do?

Fixes #15936

Problem: With entry: ["a", "b", "c"] and output.library: { type: "global" } (or assign), only exports from the last entry module (c) were exposed on the library. Exports from a and b were lost.

Cause:

  1. AbstractLibraryPlugin only called finishEntryModule for deps[deps.length - 1], so only the last entry module was marked as "used as library export"; the others could be tree-shaken or not wired for export.
  2. Bootstrap / inlined startup gave each entry module its own exports object ({}) except the last, so only the last module’s exports were assigned to the library target.

Fix:

  1. lib/library/AbstractLibraryPlugin.js: Call finishEntryModule for every entry dependency in deps, not only the last one, so all entry modules are marked as used for library export.
  2. lib/javascript/JavascriptModulesPlugin.js (bootstrap): When output.library is set and there are multiple entry modules, pass the same exports object (RuntimeGlobals.exports) to every entry module in the non-inlined startup path so they all merge into one object.
  3. lib/javascript/JavascriptModulesPlugin.js (inlined): When output.library is set and multiple entry modules are inlined, use the shared __webpack_exports__ for all of them (no per-module {}) so they merge; avoid adding a self-referential var __webpack_exports__ = __webpack_exports__ when the module already uses RuntimeGlobals.exports.

Test: Added test/configCases/library/multiple-entry-exports-15936/ with entry: ["./a.js", "./b.js", "./c.js"] and output.library: { name: "MyLib", type: "assign" }. The test asserts that MyLib.a, MyLib.b, and MyLib.c are all defined correctly.

Checklist

  • Fix is minimal and targeted
  • New test case added (configCases/library/multiple-entry-exports-15936)
  • No breaking change

…#15936)

When entry is an array (e.g. entry: ['a', 'b', 'c']) and output.library is set,
only the last entry module's exports were used. Now all entry modules'
exports are merged into the library output.

- AbstractLibraryPlugin: call finishEntryModule for every entry dependency,
  not only deps[deps.length - 1], so all entry modules are marked as used
  for library export.
- JavascriptModulesPlugin (bootstrap): when library is set and there are
  multiple entry modules, pass the same exports object to every entry
  module so they merge (non-inlined path).
- JavascriptModulesPlugin (inlined): when library is set and multiple
  entry modules are inlined, use the shared __webpack_exports__ for all
  so they merge into one object.

Added test configCases/library/multiple-entry-exports-15936.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings February 13, 2026 09:31
@changeset-bot
Copy link

changeset-bot bot commented Feb 13, 2026

⚠️ No Changeset found

Latest commit: d253bc5

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

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Feb 13, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: vvinit594 / name: Vinit Vishwakarma (d253bc5)

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug where only the last entry module's exports were exposed when using output.library with multiple entry modules (e.g., entry: ["a", "b", "c"]). The fix ensures that all entry modules' exports are aggregated into the library object by: (1) calling finishEntryModule for all entry dependencies in AbstractLibraryPlugin, not just the last one, and (2) passing the same shared exports object to all entry modules in JavascriptModulesPlugin's startup code generation.

Changes:

  • AbstractLibraryPlugin now processes all entry dependencies for library export marking
  • JavascriptModulesPlugin's bootstrap path shares exports object across all entry modules when library output is configured
  • JavascriptModulesPlugin's inlined path adds logic to merge exports from multiple entry modules
  • Test case added to verify the fix with three entry modules exporting different constants

Reviewed changes

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

Show a summary per file
File Description
lib/library/AbstractLibraryPlugin.js Changed to iterate through all entry dependencies and call finishEntryModule for each, instead of only processing the last dependency
lib/javascript/JavascriptModulesPlugin.js Added mergeLibraryEntryExports flag and logic to share RuntimeGlobals.exports across all entry modules in both inlined and bootstrap code paths
test/configCases/library/multiple-entry-exports-15936/webpack.config.js Test configuration with three entry modules and assign library type
test/configCases/library/multiple-entry-exports-15936/test.config.js Test cleanup to remove global library object
test/configCases/library/multiple-entry-exports-15936/a.js First entry module exporting constant a
test/configCases/library/multiple-entry-exports-15936/b.js Second entry module exporting constant b
test/configCases/library/multiple-entry-exports-15936/c.js Third entry module exporting constant c and containing test assertions

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

Comment on lines +1069 to +1075
if (mergeLibraryEntryExports) {
if (m.exportsArgument !== RuntimeGlobals.exports) {
startupSource.add(
`var ${m.exportsArgument} = ${RuntimeGlobals.exports};\n`
);
}
// else: module uses __webpack_exports__ from outer scope
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

When multiple entry modules are inlined with mergeLibraryEntryExports, the existing logic at lines 1020-1025 (not shown in diff) wraps each entry module in an IIFE for isolation. The export variable declarations at lines 1070-1073 are then placed inside these IIFE scopes.

For ES modules that use property assignments (e.g., __webpack_exports__.a = 1), this works because the outer __webpack_exports__ is accessed through scope chain lookup. However, if a module reassigns its exports variable (e.g., exports = {...}), the connection to the shared __webpack_exports__ would be broken, preventing export aggregation.

While ES modules typically only do property assignments, this creates a fragile dependency on module code behavior. Consider explicitly preventing IIFE wrapping when mergeLibraryEntryExports is true, or documenting this limitation.

Copilot uses AI. Check for mistakes.
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.

export in library works only for last entry module

1 participant