voidzero-dev / voidzero-dev/vite-plus

Cloudflare workerd SSR: React module duplication in HeadContent useContext when used with TanStack Start + @cloudflare/vite-plugin

Aperta
#1,671 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Rust
Stelle
5.8k
Fork
262
Merge medio
1g 34m
PR unite (30g)
135

Descrizione

## Setup

- `vite-plus` (alias `vite` → `@voidzero-dev/vite-plus-core`) `0.1.22`
- `@cloudflare/vite-plugin` `^1.37.2` (workerd SSR environment)
- `@tanstack/react-start` `^1.168.10` + `@tanstack/react-router` `^1.170.7`
- React 19, `@vitejs/plugin-react` `^6.0.2`
- bun workspaces, single app uses TanStack Start

`vite.config.ts` mirrors the working garden setup exactly (vanilla Vite 8 + same `environments.ssr.optimizeDeps.include` list + same plugin order):

\`\`\`ts
export default defineConfig({
resolve: { tsconfigPaths: true, dedupe: ["react", "react-dom"] },
environments: {
ssr: {
optimizeDeps: {
include: [
"react", "react/jsx-runtime", "react/jsx-dev-runtime",
"react-dom", "react-dom/server",
"@tanstack/react-router > @tanstack/react-store",
],
},
},
},
plugins: [
cloudflare({ viteEnvironment: { name: "ssr" } }),
agents(),
tailwindcss(),
tanstackStart(),
viteReact(),
],
});
\`\`\`

## What happens

SSR shell render of \`HeadContent\` crashes with React invalid-hook-call:

\`\`\`
TypeError: Cannot read properties of null (reading 'useContext')
at exports.useContext (deps_ssr/react.js?v=…:706)
at useRouter (@tanstack/react-router/src/useRouter.tsx:20)
at useTags (@tanstack/react-router/src/headContentUtils.tsx:213)
at HeadContent (@tanstack/react-router/src/HeadContent.dev.tsx:22)
\`\`\`

i.e. the classic two-copies-of-React-in-workerd-SSR situation that cloudflare/workers-sdk#11825 describes. Browser ends up on the JSON 500 page (\`{"status":500,"message":"HTTPError"}\`).

The exact same source tree + the exact same config, run on **vanilla Vite 8** in another project (https://github.com/voidzero-dev/garden parallel — its \`apps/web\` works fine), renders cleanly.

## Comparison

| | vanilla Vite 8 (garden) | vite-plus-core 0.1.22 (this repo) |
|---|---|---|
| Same vite.config | works | 500 with useContext null in HeadContent |
| Same plugin order | works | broken |
| Same SSR optimizeDeps.include | works | broken |

Switching this repo's catalog alias to vanilla Vite 8 doesn't fully fix it either — first \`/\` render works, but on any subsequent SSR render of the route (HMR reload, client navigate, etc.) the same useContext null surfaces.

## Suspicion

`@voidzero-dev/vite-plus-core` ships its own (rolldown-backed?) Vite that handles \`environments.ssr.optimizeDeps\` differently from upstream Vite's dep optimizer, so the React module the workerd runner ends up with isn't the same instance the route bundle imports. This trips every provider hook downstream (`useContext` in `HeadContent`, `useEffect` in `QueryClientProvider`, etc.).

Repro repo: I can put one up if helpful — but the diff against the existing TanStack Start cloudflare example is essentially "swap upstream Vite for the vite-plus-core alias and add `@cloudflare/vite-plugin`".

## Related

- https://github.com/cloudflare/workers-sdk/issues/11825
- https://github.com/TanStack/router/issues/5208

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.