voidzero-dev / voidzero-dev/vite-plus
Cloudflare workerd SSR: React module duplication in HeadContent useContext when used with TanStack Start + @cloudflare/vite-plugin
- Ngôn ngữ chính
- Rust
- Star
- 5.8k
- Fork
- 262
- Merge trung bình
- 23 giờ 41 phút
- Pull request đã merge (30 ngày)
- 138
Mô tả
## 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
Hướng dẫn đóng góp
Hướng nghiên cứu
Tái hiện lỗi với vite.config.ts được cung cấp và thiết lập SSR TanStack Start Cloudflare, sau đó so sánh với ví dụ garden vanilla Vite 8 đang hoạt động. Trước tiên, hãy lần theo environments.ssr.optimizeDeps và quá trình tải module SSR của workerd, tập trung vào việc liệu React có được khởi tạo hai lần hay không. Được xem là hoàn tất khi HeadContent và các lần render SSR tiếp theo hoàn thành mà không có lỗi invalid-hook-call.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- bun, react, typescript, vite
- Lĩnh vực
- build-system, cloud, frontend, tooling
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 48/100