Skip to content

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

Open

Description

@shkumbinhasani

Which project does this relate to?

Router

Describe the bug

The code splitter moves a module-level binding that a split option and a kept option both read into the ?tsr-shared=1 module. The split chunk (?tsr-split=…) and the shared module look those bindings up in sharedBindingsMap, and only compiling the route file fills that map. When a chunk or the shared module compiles before the route file in a process, the map is empty:

  • the chunk declares the binding again, so the chunk and the route file each hold their own copy of the state;
  • the shared-module transform returns null, so ?tsr-shared=1 is the untouched route file: it calls createFileRoute a second time and does not export the binding, while the compiled route file imports the binding from it.

This happens when the route file's output comes from a cache. A dev server that keeps transform results across restarts serves the route file without running the plugin on it, then compiles a chunk it has not cached yet, such as an errorComponent chunk nobody asked for before. It also happens in any tool that compiles modules one at a time.

Complete minimal reproducer

https://gist.github.com/shkumbinhasani/1787ba7900314a3384e3d8dbc4334674

Steps to Reproduce the Bug

  1. Clone the gist, run npm install, then npm start.

  2. The script starts a Vite dev server with tanstackRouter({ target: 'react', autoCodeSplitting: true }) and calls server.transformRequest on this route's three modules in two orders, each on a fresh server:

    const visits = { count: 0 }
    
    export const Route = createFileRoute('/')({
      loader: () => ++visits.count,
      component: () => 'visits: ' + visits.count,
    })
  3. Order A (route file, chunk, shared module) is right. Order B (chunk, shared module, route file) prints a chunk with its own const visits = { count: 0 } and a shared module that still calls createFileRoute and exports Route instead of visits.

Expected behavior

The order does not matter. In both orders the ?tsr-split=component chunk imports visits from ?tsr-shared=1, and the shared module declares and exports only visits.

Screenshots or Videos

No response

Platform

  • Router / Start Version: @tanstack/router-plugin 1.168.47; also on main (b1b1117)
  • OS: macOS
  • Browser: n/a (build time)
  • Browser Version: n/a
  • Bundler: vite
  • Bundler Version: 8.3.4

Additional context

#8504 computes the shared bindings from the source in the split and shared handlers (resolveSharedBindings), which fixes this as part of the Yuku migration. I'll open a small fix for the current plugin.

AI disclosure: Claude Code wrote this report and the reproducer, and ran the reproducer against 1.168.47.

Activity

  1. Sheraff commented on Oct 18, 2026

    @Sheraff
    Collaborator

    FWIW we're in the process of rewriting the entire compiler

  2. self-assigned this
    on Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions