Skip to content

feat: implement module tagging system for code splitting#9045

Merged
graphite-app[bot] merged 1 commit intomainfrom
04-09-feat_implement_module_tagging_system_for_code_splitting
Apr 9, 2026
Merged

feat: implement module tagging system for code splitting#9045
graphite-app[bot] merged 1 commit intomainfrom
04-09-feat_implement_module_tagging_system_for_code_splitting

Conversation

@hyf0
Copy link
Copy Markdown
Member

@hyf0 hyf0 commented Apr 9, 2026

Summary

Implements Phase 1 of the module tags design (#9017):

  • $initial tag — automatically computed during the entry BFS. Modules statically imported by user-defined entries (or in their dependency chain) are tagged $initial.
  • tags filter — manual code splitting groups can filter by tags with AND semantics. Only modules with all specified tags are captured.

Implementation

  • ModuleTagBitSetu64-based bitset (Copy, single AND+CMP for contains_all). Supports up to 64 tags.
  • ModuleTagRegistry — sealed registry mapping tag names ($initial, future $lazy) to bit indices. All registration happens in new().
  • $initial tag is computed inside determine_reachable_modules_for_entry BFS — no separate pass needed.
  • Built-in tags use $ prefix to distinguish from user-defined tags.

Test plan

  • Integration test tags_initial — entry with static + dynamic imports, verifies tags: ['$initial'] captures only statically reachable modules
  • cargo check compiles
  • just lint-rust passes
  • just build-rolldown regenerates bindings
  • TypeScript types check

🤖 Generated with Claude Code

Copy link
Copy Markdown
Member Author

hyf0 commented Apr 9, 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.

@hyf0 hyf0 force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from 51d0843 to dc7eec7 Compare April 9, 2026 06:05
@hyf0 hyf0 force-pushed the docs/design-module-tags branch from 8be3c9f to 06ead2c Compare April 9, 2026 06:05
@hyf0 hyf0 force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch 3 times, most recently from 7586674 to f00c612 Compare April 9, 2026 06:49
@hyf0 hyf0 marked this pull request as ready for review April 9, 2026 07:02
Copilot AI review requested due to automatic review settings April 9, 2026 07:02
@graphite-app graphite-app Bot changed the base branch from docs/design-module-tags to graphite-base/9045 April 9, 2026 07:04
Copy link
Copy Markdown
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

Implements Phase 1 of module tags for manual code splitting by introducing a computed $initial tag and a tags filter for manual code splitting groups (AND semantics).

Changes:

  • Add $initial tagging during the per-entry static dependency BFS and propagate tag info into splitting metadata.
  • Add tags filtering to manual code splitting groups and wire it through TS options/validation, Rust options/bindings, and generated schemas.
  • Add an integration test fixture (tags_initial) to verify $initial selection vs dynamic-only modules.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/rolldown/src/utils/validator.ts Adds tags field validation for advanced chunk group options.
packages/rolldown/src/options/output-options.ts Documents/defines BuiltinModuleTag and adds tags to CodeSplittingGroup.
packages/rolldown/src/binding.d.cts Updates generated binding typings to include tags on match groups.
crates/rolldown/src/stages/generate_stage/manual_code_splitting.rs Applies tags-based filtering when matching modules into manual groups.
crates/rolldown/src/stages/generate_stage/code_splitting.rs Computes $initial tag during static BFS and threads a tag registry into manual splitting.
crates/rolldown_common/src/types/module_tag.rs Introduces ModuleTagBitSet and ModuleTagRegistry for tag compilation/checking.
crates/rolldown_common/src/types/mod.rs Exposes the new module_tag module.
crates/rolldown_common/src/lib.rs Re-exports ModuleTagBitSet / ModuleTagRegistry.
crates/rolldown_common/src/inner_bundler_options/types/manual_code_splitting_options.rs Adds tags to MatchGroup and schema-only built-in tag enum for schemars.
crates/rolldown_binding/src/utils/normalize_binding_options.rs Passes tags through binding option normalization.
crates/rolldown_binding/src/options/binding_output_options/binding_manual_code_splitting_options.rs Adds tags to BindingMatchGroup.
crates/rolldown_testing/_config.schema.json Extends test config schema with tags and a BuiltinModuleTag enum.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/shared.js Test fixture module for static import chain.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/main.js Test entry importing shared statically and lazy dynamically.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/lazy.js Test fixture for a dynamically imported module.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/lazy-dep.js Test fixture dependency for the lazy chunk.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/artifacts.snap Snapshot for expected chunk outputs.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/_test.mjs Asserts $initial-filtered chunk contents and file set.
crates/rolldown/tests/rolldown/function/advanced_chunks/tags_initial/_config.json Configures a manual group filtered by tags: ["$initial"].

Comment thread crates/rolldown_common/src/types/module_tag.rs Outdated
Comment thread crates/rolldown/src/stages/generate_stage/manual_code_splitting.rs
Comment thread packages/rolldown/src/options/output-options.ts Outdated
Comment thread packages/rolldown/src/utils/validator.ts
@graphite-app graphite-app Bot force-pushed the graphite-base/9045 branch from 06ead2c to 806e1a0 Compare April 9, 2026 07:07
@graphite-app graphite-app Bot force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from f00c612 to 8dec60e Compare April 9, 2026 07:07
@hyf0 hyf0 force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from 8dec60e to 5bb2756 Compare April 9, 2026 07:07
@hyf0 hyf0 changed the base branch from graphite-base/9045 to main April 9, 2026 07:07
@graphite-app graphite-app Bot force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from 5bb2756 to 1491ddc Compare April 9, 2026 07:08
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 9, 2026

Deploy Preview for rolldown-rs failed.

Name Link
🔨 Latest commit d4253e2
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/69d7c73c56944f0007fc2368

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 9, 2026

Merging this PR will not alter performance

✅ 4 untouched benchmarks
⏩ 10 skipped benchmarks1


Comparing 04-09-feat_implement_module_tagging_system_for_code_splitting (c890eb4) with main (9dd533a)

Open in CodSpeed

Footnotes

  1. 10 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.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 9, 2026

Open in StackBlitz

@rolldown/browser

npm i https://pkg.pr.new/@rolldown/browser@9045

@rolldown/debug

npm i https://pkg.pr.new/@rolldown/debug@9045

@rolldown/pluginutils

npm i https://pkg.pr.new/@rolldown/pluginutils@9045

rolldown

npm i https://pkg.pr.new/rolldown@9045

@rolldown/binding-android-arm64

npm i https://pkg.pr.new/@rolldown/binding-android-arm64@9045

@rolldown/binding-darwin-arm64

npm i https://pkg.pr.new/@rolldown/binding-darwin-arm64@9045

@rolldown/binding-darwin-x64

npm i https://pkg.pr.new/@rolldown/binding-darwin-x64@9045

@rolldown/binding-freebsd-x64

npm i https://pkg.pr.new/@rolldown/binding-freebsd-x64@9045

@rolldown/binding-linux-arm-gnueabihf

npm i https://pkg.pr.new/@rolldown/binding-linux-arm-gnueabihf@9045

@rolldown/binding-linux-arm64-gnu

npm i https://pkg.pr.new/@rolldown/binding-linux-arm64-gnu@9045

@rolldown/binding-linux-arm64-musl

npm i https://pkg.pr.new/@rolldown/binding-linux-arm64-musl@9045

@rolldown/binding-linux-ppc64-gnu

npm i https://pkg.pr.new/@rolldown/binding-linux-ppc64-gnu@9045

@rolldown/binding-linux-s390x-gnu

npm i https://pkg.pr.new/@rolldown/binding-linux-s390x-gnu@9045

@rolldown/binding-linux-x64-gnu

npm i https://pkg.pr.new/@rolldown/binding-linux-x64-gnu@9045

@rolldown/binding-linux-x64-musl

npm i https://pkg.pr.new/@rolldown/binding-linux-x64-musl@9045

@rolldown/binding-openharmony-arm64

npm i https://pkg.pr.new/@rolldown/binding-openharmony-arm64@9045

@rolldown/binding-wasm32-wasi

npm i https://pkg.pr.new/@rolldown/binding-wasm32-wasi@9045

@rolldown/binding-win32-arm64-msvc

npm i https://pkg.pr.new/@rolldown/binding-win32-arm64-msvc@9045

@rolldown/binding-win32-x64-msvc

npm i https://pkg.pr.new/@rolldown/binding-win32-x64-msvc@9045

commit: 2623771

@hyf0 hyf0 force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from 1491ddc to 2623771 Compare April 9, 2026 07:16
Comment thread crates/rolldown_common/src/types/module_tag.rs Outdated
@hyf0 hyf0 force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from 2623771 to 93bbb38 Compare April 9, 2026 09:10
@hyf0 hyf0 force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from 93bbb38 to c890eb4 Compare April 9, 2026 15:02
Copy link
Copy Markdown
Member Author

hyf0 commented Apr 9, 2026

Merge activity

## Summary

Implements Phase 1 of the module tags design ([#9017](#9017)):

- **`$initial` tag** — automatically computed during the entry BFS. Modules statically imported by user-defined entries (or in their dependency chain) are tagged `$initial`.
- **`tags` filter** — manual code splitting groups can filter by tags with AND semantics. Only modules with all specified tags are captured.

## Implementation

- `ModuleTagBitSet` — `u64`-based bitset (`Copy`, single AND+CMP for `contains_all`). Supports up to 64 tags.
- `ModuleTagRegistry` — sealed registry mapping tag names (`$initial`, future `$lazy`) to bit indices. All registration happens in `new()`.
- `$initial` tag is computed inside `determine_reachable_modules_for_entry` BFS — no separate pass needed.
- Built-in tags use `$` prefix to distinguish from user-defined tags.

## Test plan

- [x] Integration test `tags_initial` — entry with static + dynamic imports, verifies `tags: ['$initial']` captures only statically reachable modules
- [x] `cargo check` compiles
- [x] `just lint-rust` passes
- [x] `just build-rolldown` regenerates bindings
- [x] TypeScript types check

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@graphite-app graphite-app Bot force-pushed the 04-09-feat_implement_module_tagging_system_for_code_splitting branch from c890eb4 to d4253e2 Compare April 9, 2026 15:35
@graphite-app graphite-app Bot merged commit d4253e2 into main Apr 9, 2026
27 of 31 checks passed
@graphite-app graphite-app Bot deleted the 04-09-feat_implement_module_tagging_system_for_code_splitting branch April 9, 2026 15:39
This was referenced Apr 15, 2026
shulaoda added a commit that referenced this pull request Apr 16, 2026
## [1.0.0-rc.16] - 2026-04-16

### 🚀 Features

- const enum cross-module inlining support (#8796) by @Dunqing
- implement module tagging system for code splitting (#9045) by @hyf0

### 🐛 Bug Fixes

- rolldown_plugin_vite_manifest: handle duplicate chunk names for CSS entries (#9059) by @sapphi-red
- improve error message for invalid return values in function options (#9125) by @shulaoda
- await async export-star init wrappers (#9101) by @thezzisu
- never panic during diagnostic emission (#9091) by @IWANABETHATGUY
- include array rest pattern in binding_identifiers (#9112) by @IWANABETHATGUY
- rolldown: set worker thread count with ROLLDOWN_WORKER_THREADS (#9086) by @fpotter
- rolldown_plugin_lazy_compilation: escape request ID in proxy modules (#9102) by @h-a-n-a
- treat namespace member access as side-effect-free (#9099) by @IWANABETHATGUY
- relax overly conservative side-effect leak check in chunk optimizer (#9085) by @IWANABETHATGUY
- runtime: release `cb` reference after `__commonJS` factory initialization (#9067) by @hyf0-agent
- `@__NO_SIDE_EFFECTS__` wrapper should not remove dynamic imports (#9075) by @IWANABETHATGUY
- rolldown_plugin_vite_import_glob: use POSIX path join/normalize for glob resolution (#9077) by @shulaoda
- emit REQUIRE_TLA error when require() loads a module with top-level await (#9071) by @jaehafe
- emit namespace declaration for empty modules in manual chunks (#8993) by @privatenumber
- rolldown_plugin_vite_import_glob: keep common base on path segment boundary (#9070) by @shulaoda
- prevent circular runtime helper imports during facade elimination (#8989) (#9057) by @IWANABETHATGUY
- correct circular dependency check in facade elimination (#9047) by @h-a-n-a
- docs: correct dead link in CodeSplittingGroup.tags JSDoc (#9051) by @hyf0
- emit DUPLICATE_SHEBANG warning when banner contains shebang (#9026) by @IWANABETHATGUY

### 🚜 Refactor

- use semantic reference flags for member write detection (#9060) by @Dunqing
- extract UsedSymbolRefs newtype wrapper (#9130) by @IWANABETHATGUY
- dedupe await wrapping in export-star init emit (#9119) by @IWANABETHATGUY
- calculate side-effect-free function symbols on demand (#9120) by @IWANABETHATGUY
- extract duplicated top-level await handling into shared helper (#9087) by @IWANABETHATGUY
- rolldown_plugin_vite_import_glob: use split_first for get_common_base (#9069) by @shulaoda
- simplify ESM init deduplication with idiomatic insert check (#9044) by @IWANABETHATGUY

### 📚 Documentation

- document runtime module placement strategy in code-splitting design (#9062) by @IWANABETHATGUY
- clarify `options` hook behavior difference with Rollup in watch mode (#9053) by @sapphi-red
- meta/design: introduce module tags (#9017) by @hyf0

### ⚡ Performance

- convert `generate_transitive_esm_init` to iterative (#9046) by @IWANABETHATGUY

### 🧪 Testing

- merge strict/non_strict test variants using configVariants (#9089) by @IWANABETHATGUY

### ⚙️ Miscellaneous Tasks

- disable Renovate auto-updates for oxc packages (#9129) by @IWANABETHATGUY
- upgrade oxc@0.126.0 (#9127) by @Dunqing
- deps: update napi to v3.8.5 (#9126) by @renovate[bot]
- deps: update dependency @napi-rs/cli to v3.6.2 (#9123) by @renovate[bot]
- move lazy-compilation design doc (#9117) by @h-a-n-a
- deps: update dependency vite-plus to v0.1.18 (#9118) by @renovate[bot]
- deps: update dependency vite-plus to v0.1.17 (#9113) by @renovate[bot]
- deps: update oxc to v0.125.0 (#9094) by @renovate[bot]
- deps: update dependency follow-redirects to v1.16.0 [security] (#9103) by @renovate[bot]
- deps: update test262 submodule for tests (#9097) by @sapphi-red
- deps: update crate-ci/typos action to v1.45.1 (#9096) by @renovate[bot]
- deps: update rust crates (#9081) by @renovate[bot]
- deps: update npm packages (#9080) by @renovate[bot]
- remove outdated TODO in determine_module_exports_kind (#9072) by @jaehafe
- rust/test: support `extendedTests: false` shorthand in test config (#9050) by @hyf0
- ci: extract shared infra-changes anchor in path filters (#9054) by @hyf0
- add docs build check to catch dead links in PRs (#9052) by @hyf0

### ❤️ New Contributors

* @thezzisu made their first contribution in [#9101](#9101)
* @fpotter made their first contribution in [#9086](#9086)
* @jaehafe made their first contribution in [#9071](#9071)
* @privatenumber made their first contribution in [#8993](#8993)

Co-authored-by: shulaoda <165626830+shulaoda@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants