Skip to content

File-system routing requires ssr: true for the dev server (lift this limitation) #124

Description

@uhyo

Summary

Built-in file-system routing (the experimental fsRoutes option, added in #123) only renders in vite dev when ssr: true is set. With the default ssr: false, the dev server renders the app shell but the page content never appears. Production builds (vite build) are unaffected and work with ssr either way.

We currently work around this by requiring/documenting ssr: true for fs-routing. This issue tracks lifting that limitation so ssr: false works in dev too.

Root cause

fs-routing renders pages through FUNSTACK Router's <Router> (a client component) and passes the page components as server-component route data:

<Router routes={[{ path: "/about", component: <AboutPage /> }]} ssr={{ path }} />
  • In a production build (ssr: false), the RSC payload is pre-rendered at build time, so the server components in routes are rendered to their output and serialized. ✅

  • In vite dev with ssr: false, the app is rendered on the client from the RSC stream. @vitejs/plugin-rsc serializes the server-component route data as an eval'd dev-JSX source reference (a $E…function AboutPage(){ _jsxDEV(...) } entry in the flight data). When the browser evaluates it, the jsxDEV import resolves to the client's optimized react/jsx-runtime, which doesn't export it:

    SyntaxError: The requested module '/node_modules/.vite/deps/react_jsx-runtime.js?v=…'
    does not provide an export named 't'
    

    React's error boundary then renders the "Unexpected Error" shell, so no page content appears.

  • In vite dev with ssr: true, pages are rendered on the server, so the broken client eval path is never taken. ✅

This is not specific to the fsRoutes codegen — the same failure reproduces with the equivalent hand-written userland pattern (module-level routes with component: <Page />, ssr: false). It's an interaction between "server components passed as data to a client component" and @vitejs/plugin-rsc's dev serialization.

Reproduction

  1. Configure fsRoutes (or a hand-written <Router routes={[{ component: <ServerPage /> }]} />) without ssr: true.
  2. vite dev, open any route in a browser.
  3. The shell loads but page content is missing; the console shows the react/jsx-runtime jsxDEV/'t' export error above.

packages/static/e2e/tests-dev/fs-routing.spec.ts reproduces this when the fixture's ssr is false.

Possible directions

  • Render the matched route on the server even when ssr: false in dev (mirror the production pre-render path), so the client receives rendered output rather than an eval'd server-component reference.
  • Investigate whether @vitejs/plugin-rsc can serialize server components passed as client-component props consistently between dev and build (upstream fix or configuration).
  • Align the dev jsx runtime so the eval'd dev-JSX (jsxDEV) resolves correctly on the client.

Workaround (current)

Set ssr: true when using fsRoutes. This is documented in the File-System Routing guide and used by the example and e2e fixture.

Related: #123

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions