Skip to content

fix(router-plugin): work out shared bindings when a split chunk compiles first - #8756

Open
shkumbinhasani wants to merge 1 commit into
TanStack:mainfrom
shkumbinhasani:fix/router-plugin-shared-bindings-order
Open

shkumbinhasani wants to merge 1 commit into
TanStack:mainfrom
shkumbinhasani:fix/router-plugin-shared-bindings-order

Conversation

@shkumbinhasani

@shkumbinhasani shkumbinhasani commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

🎯 Changes

Fixes #8754.

The split (?tsr-split=…) and shared (?tsr-shared=1) handlers read a route's shared bindings from sharedBindingsMap, which only the reference compile fills. When one of them compiled first in a process, as when a dev server serves the route file's output from a cache, the chunk declared its own copy of the shared bindings, and the shared module was left as the untouched route file.

  • getSharedBindings(baseId, code) returns the recorded bindings, or computes them from the module's source and records them. The virtual and shared handlers use it.
  • getSplitGroupings is the grouping lookup (route codeSplitGroupings, then splitBehavior, then defaultBehavior, with the same validation), moved out of handleCompilingReferenceFile so both paths use it.
  • The reference compile now records an empty set for a route without shared bindings instead of deleting its entry, so that route's chunks don't compute the bindings again.
  • ARCHITECTURE-CODE-SPLITTING.md describes the fallback.

In the usual order (route file first) nothing changes: the handlers read what the reference compile recorded. #8504 drops the map and computes the bindings in each handler (resolveSharedBindings); this keeps the map so the usual order does no extra work.

Tests:

  • code-splitter-plugin-pipeline.test.ts: compiles a route's chunk and shared module before its route file, and the shared module first, with the default groupings and with splitBehavior, and expects the same modules as compiling the route file first. Both cases fail on main.
  • The reproducer in router-plugin: split chunk and shared module miss shared bindings when compiled before the route file #8754 gives the same output in both orders with this build.
  • pnpm nx run @tanstack/router-plugin:test:unit (902 passed, 3 expected fail), test:types and test:eslint pass; @tanstack/start-plugin-core:test:unit passes.

AI disclosure: Claude Code wrote this change, its tests and this description.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with the relevant test commands, or tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed code-split output when route files, split chunks, or shared modules are processed in different orders. Builds now preserve consistent shared-binding behavior, including when route output is served from cache.
  • Documentation
    • Updated code-splitting guidance to reflect how shared bindings are resolved when dependent modules are processed before their route files.

…les first

Split and shared modules read the bindings their route shares from a map
that compiling the route file fills. When a `?tsr-split=` or `?tsr-shared=1`
module compiled first in a process, as when a dev server serves the route
file's output from a cache, the map was empty: the chunk declared its own
copy of the shared bindings, and the shared module was left as the
untouched route file.

`getSharedBindings` now computes them from the module's source with the
same groupings the route file uses (`getSplitGroupings`, moved out of the
reference handler) and records them. The reference compile also records
routes without shared bindings, so chunks of those routes don't compute
them again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 47f683b

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

This PR includes changesets to release 7 packages
Name Type
@tanstack/router-plugin Patch
@tanstack/router-vite-plugin Patch
@tanstack/start-plugin-core Patch
@tanstack/react-start-rsc Patch
@tanstack/react-start Patch
@tanstack/solid-start Patch
@tanstack/vue-start Patch

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

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: TanStack/router/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cf2ccac3-244e-4584-a73a-e122d23b2962
📥 Commits

Reviewing files that changed from the base of the PR and between b1b1117 and 47f683b.

📒 Files selected for processing: 4
  • .changeset/shared-bindings-before-route-file.md
  • packages/router-plugin/ARCHITECTURE-CODE-SPLITTING.md
  • packages/router-plugin/src/core/router-code-splitter-plugin.ts
  • packages/router-plugin/tests/code-splitter-plugin-pipeline.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

The router plugin now resolves shared bindings when a split chunk or shared module compiles before its route file. It computes and caches bindings from a known route’s source and grouping configuration. Tests compare output across compilation orders.

Changes: Shared-binding resolution

Layer / File(s) Summary
Resolve and cache route bindings
packages/router-plugin/src/core/router-code-splitter-plugin.ts
The plugin extracts route grouping resolution and adds a helper that returns cached bindings or computes and stores them for a known route.
Use resolved bindings in dependent transforms
packages/router-plugin/src/core/router-code-splitter-plugin.ts, packages/router-plugin/tests/code-splitter-plugin-pipeline.test.ts, packages/router-plugin/ARCHITECTURE-CODE-SPLITTING.md, .changeset/shared-bindings-before-route-file.md
Virtual-route and shared-module transforms use the resolver. Tests compare compilation orders. The architecture documentation and changeset describe the behavior.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant SplitModuleTransform
  participant getSharedBindings
  participant sharedBindingsMap
  participant RouteSource
  SplitModuleTransform->>getSharedBindings: Resolve bindings for the route
  getSharedBindings->>sharedBindingsMap: Look up cached bindings
  alt Cache miss
    getSharedBindings->>RouteSource: Read source and route grouping configuration
    getSharedBindings->>sharedBindingsMap: Store computed bindings
  end
  getSharedBindings-->>SplitModuleTransform: Return bindings or undefined
Loading

Suggested reviewers: schiller-manuel, sheraff

Merge Risk: ⚪ Minimal · up to 47f68

The change makes split chunk and shared module output independent of compile order. No actionable merge-blocking risk was identified.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (2 skipped: 2 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main fix: resolving shared bindings when a split chunk compiles before its route file.
Description check Passed The description follows the required template. It explains the change and motivation, identifies the issue, documents testing, discloses AI authorship, and includes a changeset. One checklist item rem…
Linked Issues check Passed The pull request meets the coding requirements in [#8754]. getSharedBindings() computes and records bindings when a split or shared module runs first. getSplitGroupings() applies the route, `split…
Out of Scope Changes check Passed The changes stay within [#8754]. The implementation fixes order-independent shared bindings. The tests reproduce the reported compile orders. The architecture documentation and changeset document the …
Full details: Description check

Explanation

The description follows the required template. It explains the change and motivation, identifies the issue, documents testing, discloses AI authorship, and includes a changeset. One checklist item remains unchecked, but the description is otherwise complete.

Full details: Linked Issues check

Explanation

The pull request meets the coding requirements in [#8754]. getSharedBindings() computes and records bindings when a split or shared module runs first. getSplitGroupings() applies the route, splitBehavior, and default grouping rules. The reference path records empty binding sets. The virtual and shared handlers use the resolver. The added parameterized tests cover both dependent-module orders and default and splitBehavior groupings.

Full details: Out of Scope Changes check

Explanation

The changes stay within [#8754]. The implementation fixes order-independent shared bindings. The tests reproduce the reported compile orders. The architecture documentation and changeset document the same behavior and release impact. No unrelated product behavior is changed.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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.

router-plugin: split chunk and shared module miss shared bindings when compiled before the route file

1 participant