Skip to content

TanStack Start (RSC): route component does not HMR when its file has a co-located createServerFn #7618

@sreetamdas

Description

@sreetamdas

Which project does this relate to?

Start

Describe the bug

In RSC mode, a route component does not Hot Module Reload when its route file also contains a co-located createServerFn (e.g. a loader server function in the same file as the route component).

On editing the route component's JSX, the terminal shows only:

(rsc) hmr update /src/routes/index.tsx?tss-serverfn-split

…with no client update, so the DOM never changes — and there is no full reload either. Moving the createServerFn into a separate file restores Fast Refresh, which is the tell that this is specifically about co-location.

I've traced the root cause to @vitejs/plugin-rsc and opened a proposed fix upstream: vitejs/vite-plugin-react#1248. Filing here for visibility/tracking (so Start users hitting "my route won't HMR" find the cause + workaround, and so the @vitejs/plugin-rsc bump is tracked once it lands).

Root cause (short version): the route file's createServerFn puts the file in the rsc module graph. @vitejs/plugin-rsc's client hotUpdate returns [] for any file in the rsc graph that isn't inside a "use client" boundary (a guard to avoid full reloads from server-only files watched as style deps, e.g. Tailwind/addWatchFile). The route component is a genuine client module (imported by the client route tree) but isn't a "use client" reference, so its client HMR is wrongly suppressed.

Workaround: move the createServerFn/server code into a separate (e.g. *.server.ts) module and import it into the route file.

Complete minimal reproducer

https://github.com/sreetamdas/tanstack-rsc-hmr-co-located-serverfn-repro

Steps to Reproduce the Bug

  1. pnpm install && pnpm dev and open http://localhost:3000.
  2. Click Increment once (so Count: 1) to seed client state.
  3. In src/routes/index.tsx, edit the <h1 data-testid="marker"> text (edit-me-baseline → anything) and save.
  4. Observe: the heading does not update; the terminal logs only (rsc) hmr update …?tss-serverfn-split; no full reload.
  5. For contrast: move getServerData into a separate file and import it — HMR now works (heading updates, counter preserved).

Expected behavior

Editing a route component's JSX should Fast Refresh the component in dev, regardless of whether the route file also defines a createServerFn. Server-only code co-located in the file should not strip the route component's client HMR boundary.

Platform

  • Router / Start Version: @tanstack/react-start ^1.168.25, @tanstack/react-router ^1.170.15
  • OS: macOS
  • Browser: Chrome
  • Bundler: vite ^8
  • Bundler plugin: @vitejs/plugin-rsc 0.5.27

Additional context

Proposed upstream fix (with full analysis): vitejs/vite-plugin-react#1248 — only suppress the client HMR when the file has no non-CSS client importers (mirroring the existing rsc-branch's importers.every(isCSSRequest) check), so genuine client modules co-located with rsc-graph code keep Fast Refresh.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions