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.

@nx-cloud

nx-cloud Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 47f683b

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 14m 33s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 29s View ↗

☁️ Nx Cloud last updated this comment at 2026-10-19 07:06:28 UTC

@pkg-pr-new

pkg-pr-new Bot commented Oct 19, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@8756

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@8756

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@8756

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@8756

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@8756

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@8756

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@8756

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@8756

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@8756

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@8756

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@8756

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@8756

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@8756

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@8756

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@8756

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@8756

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@8756

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@8756

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@8756

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@8756

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@8756

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@8756

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@8756

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@8756

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@8756

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@8756

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@8756

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@8756

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@8756

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@8756

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@8756

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@8756

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@8756

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@8756

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@8756

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@8756

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@8756

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@8756

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@8756

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@8756

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@8756

commit: 47f683b

@codspeed

codspeed Bot commented Oct 19, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 9.45%

⚠️ 41 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

ℹ️ 29 benchmarks have no flame graph

The flamegraph could not be generated because too much time was spent in runtime internals, making the visualization not useful for performance analysis.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 193 untouched benchmarks
⏩ 3 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
⚡ Memory mem client navigation-churn (solid) 113.8 KB 104 KB +9.45%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing shkumbinhasani:fix/router-plugin-shared-bindings-order (47f683b) with main (b1b1117)

Open in CodSpeed

Footnotes

  1. 3 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. ↩

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