Skip to content

Comments

feat(lazy-barrel): skip plain imports in side-effect-free modules#7986

Closed
shulaoda wants to merge 2 commits intomainfrom
01-21-feat_lazy-barrel_skip_plain_imports_in_side-effect-free_modules
Closed

feat(lazy-barrel): skip plain imports in side-effect-free modules#7986
shulaoda wants to merge 2 commits intomainfrom
01-21-feat_lazy-barrel_skip_plain_imports_in_side-effect-free_modules

Conversation

@shulaoda
Copy link
Member

@shulaoda shulaoda commented Jan 21, 2026

Since we require the barrel file to be marked with moduleSideEffects: false, I guess we should remove these imports to be consistent.

Originally posted by @sapphi-red in #7969 (comment)

Copy link
Member Author

shulaoda commented Jan 21, 2026


How to use the Graphite Merge Queue

Add the label graphite: merge-when-ready to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@shulaoda shulaoda force-pushed the 01-21-feat_lazy-barrel_skip_plain_imports_in_side-effect-free_modules branch from e9a8272 to 1f5ce1c Compare January 21, 2026 08:31
Base automatically changed from 01-20-docs_add_in-depth_documentation_for_lazy_barrel_optimization to main January 21, 2026 08:31
@shulaoda shulaoda marked this pull request as ready for review January 21, 2026 08:31
Copilot AI review requested due to automatic review settings January 21, 2026 08:31
@shulaoda shulaoda force-pushed the 01-21-feat_lazy-barrel_skip_plain_imports_in_side-effect-free_modules branch from 1f5ce1c to 869aaeb Compare January 21, 2026 08:32
@netlify
Copy link

netlify bot commented Jan 21, 2026

Deploy Preview for rolldown-rs ready!

Name Link
🔨 Latest commit 40dd19a
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/6971d301c7bd2900087cef06
😎 Deploy Preview https://deploy-preview-7986--rolldown-rs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

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 implements skipping of plain imports (like import './module', import {} from './module', and export {} from './module') in side-effect-free modules when lazy barrel optimization is enabled. Since barrel files must be marked as moduleSideEffects: false for lazy barrel optimization, these plain imports that don't contribute to exports can be safely skipped to further optimize build performance.

Changes:

  • Added IsPlainImport flag to track plain import statements that don't import any symbols
  • Updated AST scanner to mark plain imports during module scanning
  • Modified module loader to skip loading plain imports in side-effect-free modules
  • Added documentation explaining the plain import optimization behavior
  • Added test case to verify plain imports are correctly skipped

Reviewed changes

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

Show a summary per file
File Description
crates/rolldown_common/src/types/import_record.rs Adds new IsPlainImport bitflag to identify plain import statements
crates/rolldown/src/ast_scanner/mod.rs Sets IsPlainImport flag when scanning import declarations and export declarations with empty specifiers
crates/rolldown/src/module_loader/module_loader.rs Implements logic to skip loading plain imports in side-effect-free modules during lazy barrel optimization
docs/in-depth/lazy-barrel-optimization.md Documents the plain imports behavior, reorganizes sections, and updates configuration examples
packages/rolldown/tests/fixtures/lazy-barrel/plain-import/* Adds comprehensive test case verifying plain imports are skipped in side-effect-free barrel modules

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

Copilot AI review requested due to automatic review settings January 21, 2026 08:37
Copy link
Contributor

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

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.


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

@github-actions
Copy link
Contributor

github-actions bot commented Jan 21, 2026

Benchmarks Rust

  • target: main(f09a561)
  • pr: 01-21-feat_lazy-barrel_skip_plain_imports_in_side-effect-free_modules(40dd19a)
group                                                        pr                                     target
-----                                                        --                                     ------
bundle/bundle@multi-duplicated-top-level-symbol              1.00     74.4±2.54ms        ? ?/sec    1.00     74.7±1.96ms        ? ?/sec
bundle/bundle@multi-duplicated-top-level-symbol-sourcemap    1.00     79.5±2.28ms        ? ?/sec    1.03     82.0±2.38ms        ? ?/sec
bundle/bundle@rome_ts                                        1.00    107.2±3.53ms        ? ?/sec    1.00    107.2±3.28ms        ? ?/sec
bundle/bundle@rome_ts-sourcemap                              1.00    117.6±2.82ms        ? ?/sec    1.00    117.4±1.87ms        ? ?/sec
bundle/bundle@threejs                                        1.01     38.3±2.24ms        ? ?/sec    1.00     37.9±2.17ms        ? ?/sec
bundle/bundle@threejs-sourcemap                              1.00     42.7±0.79ms        ? ?/sec    1.00     42.5±0.81ms        ? ?/sec
bundle/bundle@threejs10x                                     1.00    373.9±5.50ms        ? ?/sec    1.02    379.6±6.25ms        ? ?/sec
bundle/bundle@threejs10x-sourcemap                           1.00    430.1±4.80ms        ? ?/sec    1.01    435.7±4.88ms        ? ?/sec
scan/scan@rome_ts                                            1.02     84.7±1.94ms        ? ?/sec    1.00     82.8±2.39ms        ? ?/sec
scan/scan@threejs                                            1.02     29.6±1.72ms        ? ?/sec    1.00     29.0±0.49ms        ? ?/sec
scan/scan@threejs10x                                         1.02    297.4±4.54ms        ? ?/sec    1.00    293.0±5.66ms        ? ?/sec

export {} from './module'; // empty re-export
```

In **side-effect-free** modules, these plain imports are skipped. Otherwise, they are loaded normally.
Copy link
Member

Choose a reason for hiding this comment

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

Is the description proper? ModuleA's not having side effect doesn't mean its dependency don't have side effect.

Copy link
Member

Choose a reason for hiding this comment

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

Just be sure our behavior is aligned with other bundlers.

Copy link
Member Author

@shulaoda shulaoda Jan 21, 2026

Choose a reason for hiding this comment

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

import './module'; // side-effect import
import {} from './module'; // empty import
export {} from './module'; // empty re-export

Rspack will eagerly load the first two cases by default, but it will eliminate the last one. Since export {} from '..' is invalid syntax and very uncommon, I didn’t handle it and treated it as import '..' instead.
That said, your point also makes sense. We don’t necessarily need to match Rspack’s behavior, but I need think through whether removing these could introduce any potential issues. 🤔

Rollup works like:

See #7969 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

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

Let me think this through again — I have a feeling something’s off.

Copy link
Member Author

Choose a reason for hiding this comment

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

It’s not just Rspack — I should also look at how Turbopack and Parcel handle the constraints and behavior around Lazy Barrel. I’ll share my conclusions afterward.

Copy link
Member Author

@shulaoda shulaoda Jan 21, 2026

Choose a reason for hiding this comment

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

I’ve done some research, and aside from Rspack’s behavior mentioned earlier, Parcel’s behavior is consistent with our new implementation. For side-effect-free modules, import './module', import {} from './module', and export {} from './module' are not eagerly loaded. Parcel also allows configuring sideEffects at both the module and package level.

Turbopack follows a similar behavior, although it only supports configuring sideEffects at the package level.

Based on this, I believe our new implementation is correct. We need to fully trust the user’s explicit side-effect-free declarations; otherwise, Lazy Barrel cannot be implemented in a sound and meaningful way.

^cc @sapphi-red

Copy link
Member

Choose a reason for hiding this comment

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

It seems I was misunderstanding what "marking a module as sideeffect" means.
#8005 (comment)

@sapphi-red sapphi-red force-pushed the 01-21-feat_lazy-barrel_skip_plain_imports_in_side-effect-free_modules branch from b589854 to 40dd19a Compare January 22, 2026 07:34
@shulaoda shulaoda marked this pull request as draft January 22, 2026 09:52
@shulaoda shulaoda closed this Jan 26, 2026
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.

3 participants