Repository navigation
Description
Describe the bug
Description
Vite module runner can expose an incomplete facade namespace during cold SSR evaluation when a facade imports a module, later re-exports * from the same module, and an intervening dependency cycles back to the facade.
This can cause valid native ESM to fail in SSR with runtime errors like:
TypeError: createThing is not a functionReduced Module Graph
facade.js
|
| import { createStart } from './core.js'
v
core.js
facade.js
|
| export { client } from './client.js'
v
client.js
|
v
start.js
|
v
middleware.js
|
| import { createThing } from './facade.js'
v
facade.js
|
| returns partial in-flight namespace
v
missing createThing from later export * from './core.js'Reduced Source Shape
// facade.js
import { createStart } from './core.js'
export { client } from './client.js'
export * from './core.js'
export { createStart }// core.js
export var createThing = (value) => value
export var createStart = () => {
return { started: true }
}// client.js
import { start } from './start.js'
export const client = start()// start.js
import { createStart } from './facade.js'
import { middleware } from './middleware.js'
export function start() {
return { ...createStart(), middleware }
}// middleware.js
import { createThing } from './facade.js'
export const middleware = createThing('middleware')Expected Behavior
This works in native ESM:
node --input-type=module -e "import('./facade.js').then((m) => console.log(m.client))"Expected output:
{ started: true, middleware: 'middleware' }The circular import observes createThing through the facade because facade.js already imported ./core.js before evaluating the client re-export.
Actual Behavior
In Vite SSR/module-runner, the circular import can observe the facade before the later transformed export * from './core.js' has registered its runtime __vite_ssr_exportAll__() getters.
The facade namespace is returned as partial exports, but it does not contain the wildcard export yet.
Result:
TypeError: createThing is not a functionReal-World Case
This appears in TanStack Start cold SSR startup (see TanStack/router#7459).
The public @tanstack/react-start facade imports @tanstack/react-start-client, and that client path eventually imports #tanstack-start-entry, which points back to the app's src/start.ts.
At the same time, app code imports createStart / createMiddleware from @tanstack/react-start.
Simplified graph:
src/start.ts
|
| import { createStart } from '@tanstack/react-start'
v
@tanstack/react-start
|
| import { Hydrate } from '@tanstack/react-start-client'
v
@tanstack/react-start-client
|
| export { hydrateStart }
v
@tanstack/start-client-core/client/hydrateStart
|
| import { startInstance } from '#tanstack-start-entry'
v
src/start.ts
|
| imports middleware
v
middleware.ts
|
| import { createMiddleware } from '@tanstack/react-start'
v
@tanstack/react-start
|
| partial in-flight facade namespace
v
missing createMiddleware from export * from '@tanstack/start-client-core'The package facade has this emitted shape:
import { createServerFn } from '@tanstack/start-client-core'
import { Hydrate } from '@tanstack/react-start-client'
export * from '@tanstack/start-client-core'
export { Hydrate, createServerFn, useServerFn }Since createMiddleware is only available through export *, Vite's partial namespace does not include it when the cycle returns.
Reproduction
see above
Steps to reproduce
No response
System Info
reproduced with vite 8.0.14Used Package Manager
pnpm
Logs
No response
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
Activity
fix(deps): update tanstack-router monorepo (#1742)
fix: contornar bug de reentrancia circular do TanStack Start (createC…