Visitar URL original
Refine namespace handling by lukastaegert · Pull Request #6230 · rollup/rollup · GitHub
Skip to content

Refine namespace handling - #6230

Merged
lukastaegert merged 20 commits into
masterfrom
refine-namespace-handling
Jan 22, 2026
Merged

lukastaegert merged 20 commits into
masterfrom
refine-namespace-handling

Conversation

@lukastaegert

@lukastaegert lukastaegert commented Jan 4, 2026 •

Copy link
Copy Markdown
Member

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

List any relevant issue numbers:

Description

When looking into #6120, I found the current handling of module exports and namespaces very limiting. This PR implements several changes and improvements:

  • deduplicate logic between NamespaceVariable and Module
  • do not always include the entire namespace in certain situations when only some properties are needed to improve tree-shaking
  • establish a "live-connection" between dynamic imports and namespaces in some situations for improved tree-shaking
  • enforce consistent order of generated exports and re-exports based on their names. This only affects export { foo, bar } statements.

This implies the following changes:

  • When using const ns = await import(), you get full deep tree-shaking support for unused imports and object properties, even if the usages are elsewhere in the code.
  • When using import(…).then(ns => ), you only get top-level export tree-shaking. This is however a limit of the function property tree-shaking logic. If you use destructuring import(…).then(({ a, b: {c}}) => ), you instead get one-level deep property tree-shaking for the destructured variables depending on included variable usages.
  • When calling a namespace member via property access, i.e. ns.foo(), we now always include the entire namespace. The reason is that at the moment, we cannot easily track if ns.foo would access this, and if it did, it needs access to the entire namespace. This might be improved in the future.

@vercel

vercel Bot commented Jan 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
rollup Ready Ready Preview, Comment Jan 21, 2026 5:24am

Request Review

@lukastaegert lukastaegert changed the title Do not always include entire namespace when used as variable Refine namespace handling Jan 4, 2026
@github-actions

github-actions Bot commented Jan 4, 2026 •

Copy link
Copy Markdown

Thank you for your contribution! ❤️

You can try out this pull request locally by installing Rollup via

npm install rollup/rollup#refine-namespace-handling

Notice: Ensure you have installed the latest nightly Rust toolchain. If you haven't installed it yet, please see https://www.rust-lang.org/tools/install to learn how to download Rustup and install Rust.

or load it into the REPL:
https://rollup-hx9642wbb-rollup-js.vercel.app/repl/?pr=6230

@github-actions

github-actions Bot commented Jan 4, 2026 •

Copy link
Copy Markdown

Performance report

  • BUILD: 7028ms, 830 MB (-3%)
    • initialize: 0ms, 24.5 MB
    • generate module graph: 2627ms, 637 MB
      • generate ast: 1380ms (+31ms, +2.3%), 626 MB
    • sort and bind modules: 403ms, 702 MB
    • mark included statements: 3978ms, 830 MB (-3%)
      • treeshaking pass 1: 2352ms, 829 MB
      • treeshaking pass 2: 458ms, 844 MB (+3%)
      • treeshaking pass 3: 394ms, 828 MB (-3%)
      • treeshaking pass 4: 382ms, 837 MB
      • treeshaking pass 5: 380ms, 830 MB (-3%)
  • GENERATE: 681ms, 910 MB
    • initialize render: 0ms, 830 MB (-3%)
    • generate chunks: 39ms (-11ms, -21.7%), 844 MB
      • optimize chunks: 0ms, 836 MB
    • render chunks: 632ms (+13ms, +2.2%), 883 MB
    • transform chunks: 17ms, 910 MB
    • generate bundle: 0ms, 910 MB

@codecov

codecov Bot commented Jan 4, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.46524% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.83%. Comparing base (6764d54) to head (2aadbf0).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/Module.ts 98.41% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6230      +/-   ##
==========================================
+ Coverage   98.81%   98.83%   +0.01%     
==========================================
  Files         272      273       +1     
  Lines       10717    10692      -25     
  Branches     2869     2849      -20     
==========================================
- Hits        10590    10567      -23     
+ Misses         85       82       -3     
- Partials       42       43       +1     

☔ 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.

@lukastaegert
lukastaegert force-pushed the refine-namespace-handling branch from d76d09e to 59eae9f Compare January 4, 2026 06:56
@lukastaegert
lukastaegert force-pushed the refine-namespace-handling branch from 474fdb0 to 6ec3981 Compare January 4, 2026 20:28
@lukastaegert
lukastaegert force-pushed the refine-namespace-handling branch from 8ffc416 to be37866 Compare January 5, 2026 12:54
@lukastaegert
lukastaegert force-pushed the refine-namespace-handling branch from 0d6bc0e to 42825c0 Compare January 10, 2026 07:07
@lukastaegert
lukastaegert force-pushed the refine-namespace-handling branch from b279ea7 to 43af75e Compare January 16, 2026 13:48
@lukastaegert
lukastaegert marked this pull request as ready for review January 16, 2026 15:41
Copilot AI review requested due to automatic review settings January 16, 2026 15:41

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

This PR refines namespace handling in Rollup with significant improvements to tree-shaking and module execution tracking for dynamic imports.

Changes:

  • Refactored namespace variable handling to deduplicate logic between NamespaceVariable and Module
  • Implemented smarter tree-shaking for namespaces by only including accessed properties instead of entire namespaces
  • Added "live-connection" tracking for dynamic imports via new PromiseHandler classes to improve tree-shaking of import().then() patterns
  • Restructured module export tracking using getExportedVariablesByName() instead of separate getAllExportNames() and getMemberVariables()

Reviewed changes

Copilot reviewed 151 out of 152 changed files in this pull request and generated 59 comments.

Show a summary per file
File Description
src/ast/variables/PromiseHandler.ts New file introducing ObjectPromiseHandler and EmptyPromiseHandler classes for tracking dynamic import promise chains
src/ast/variables/NamespaceVariable.ts Refactored to use module's exported variables directly, added includeMemberPath() for selective inclusion, removed getMemberVariables()
src/ast/nodes/ImportExpression.ts Major rewrite to track dynamic import resolution and establish live connections through promise handlers
src/Module.ts Consolidated export tracking with getExportedVariablesByName(), removed getAllExportNames(), getReexports(), simplified includeAllExports()
src/ast/nodes/MemberExpression.ts Added promiseHandler property to handle promise chain member access
test/function/samples/* Multiple new test cases for namespace mutations and dynamic import tree-shaking
test/form/samples/* Updated expected outputs reflecting improved tree-shaking
test/chunking-form/samples/* New tests for dynamic import object property tree-shaking

Add general caching. The idea is to eventually merge this with the caching in
NamespaceVariabe.getMemberVariables
This will make it easier to handle includes etc.
Instead of doing static analysis, this dynamically links the namespace to its
usage.
Currently, this is not as good, some test cases need to be analyzed if we can
improve here.
* It was not easily to support optimizing (await import()).foo() because we
  cannot easily track if `foo` accesses `this`, in which case it could see the
  entire namespace. Added a regression test for this.
* As .catch and .finally do not change property inclusion, we can now optimize
  cases where a .catch or .finally is followed by a .then
* There was a bug in the synthetic namespace inclusion. Fixing this allows
tree-shaking for synthetic namespaces.
This also simplifies return value deoptimization
@lukastaegert
lukastaegert force-pushed the refine-namespace-handling branch from 2241ea5 to 2aadbf0 Compare January 21, 2026 05:22
@lukastaegert
lukastaegert merged commit 18ccab2 into master Jan 22, 2026
48 checks passed
@lukastaegert
lukastaegert deleted the refine-namespace-handling branch January 22, 2026 05:08
@github-actions

Copy link
Copy Markdown

This PR has been released as part of rollup@4.56.0. You can test it via npm install rollup.

This branch was successfully deployed

1 active deployment
Preview — 2aadbf01 Deployed Jan 21, 2026 by vercel[bot]
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