tanstack-start
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTanStack Start (React) — RC-Ready Playbook
TanStack Start(React)——候选发布版实用指南
Full-stack React on TanStack Router with per-route SSR/CSR, file-based routing, server functions, and first-class Cloudflare Workers support.
基于TanStack Router的全栈React方案,支持按路由配置SSR/CSR、文件式路由、服务端函数,以及一流的Cloudflare Workers支持。
Use this skill when
适用场景
- Building a greenfield React app that needs route-level SSR/CSR/SSG switches.
- Migrating from Next.js/React Router while keeping file-based routing + API routes.
- Shipping to edge runtimes (Workers) with typed server functions and bindings.
- You want predictable routing with type-safe params/search + built-in preloading.
- 构建需要按路由切换SSR/CSR/SSG模式的全新React应用。
- 从Next.js/React Router迁移,同时保留文件式路由与API路由。
- 部署到边缘运行时(Workers),使用类型化服务端函数和绑定。
- 需要具备类型安全参数/搜索、内置预加载功能的可预测路由。
What’s inside
包含内容
- References: quickstart/layout, rendering modes, server functions, Cloudflare hosting, execution/auth, plus new routing/data/navigation/devtools guides.
- Script: scaffolds Start + Workers + binding types.
scripts/bootstrap-cloudflare-start.sh <app> - Troubleshooting: hydration, API routing, bindings, navigation/preloading failures.
- 参考文档:快速入门/布局、渲染模式、服务端函数、Cloudflare托管、执行/认证,以及新增的路由/数据/导航/开发工具指南。
- 脚本:可快速搭建Start + Workers + 绑定类型的项目。
scripts/bootstrap-cloudflare-start.sh <app> - 故障排查:hydration、API路由、绑定、导航/预加载失败问题的解决方法。
Quick Start (React)
快速开始(React)
bash
npm create @tanstack/start@latest my-app
cd my-app
npm run devManual installs (all bundle targets are supported): add + with your bundler plugin (, , or ) per the official install guides.
@tanstack/react-router@tanstack/react-startvitewebpackesbuildbash
npm create @tanstack/start@latest my-app
cd my-app
npm run dev手动安装(支持所有打包工具):根据官方安装指南,添加 + ,并配置对应的打包器插件(、或)。
@tanstack/react-router@tanstack/react-startvitewebpackesbuildCore layout reminder
核心布局提示
- file-based routes → router tree, automatic code-splitting + data preloading.
app/routes/** - hydrates
app/entry.client.tsx;<StartClient />wrapsapp/entry.server.tsx.createServerEntry - or
app/config.tssetsapp/start.ts,defaultSsr, middleware, and context.spaMode
- 文件式路由 → 生成路由树,自动代码分割 + 数据预加载。
app/routes/** - 用于激活
app/entry.client.tsx;<StartClient />包裹app/entry.server.tsx。createServerEntry - 或
app/config.ts设置app/start.ts、defaultSsr、中间件和上下文。spaMode
Routing + Data Best Practices
路由与数据最佳实践
- Type-safe params & search: infers path params; add
createFileRoute()(zod) to parse and coerce search params.validateSearch - Route matching order is deterministic (index → static → dynamic → splat); rely on this when adding catch-alls.
- Loaders run once per location change; return plain data, throw /
redirect()for control flow.notFound() - Data mutations: colocate /server functions; keep loaders read-only and invalidate via
actionafter mutation.router.invalidate() - TanStack Query bridge: create a in router context and
QueryClientinside loaders to dedupe fetches.ensureQueryData - Deferred/external data: stream partial data or read from external loaders; prefer suspense-friendly responses.
- Head management: set per route for
head/meta; derive from loader data to keep SEO consistent.<title> - Not-found/auth: throw or
notFound()in loaders/middleware; use error boundaries for UX.redirect()
Example route (typed search + data-only SSR):
ts
// app/routes/posts.$postId.tsx
import { createFileRoute, redirect } from '@tanstack/react-router'
import { z } from 'zod'
export const Route = createFileRoute('/posts/$postId')({
validateSearch: z.object({ preview: z.boolean().optional() }),
ssr: 'data-only',
loader: async ({ params, search, context }) => {
const post = await context.queryClient.ensureQueryData(['post', params.postId], () =>
fetch(`/api/posts/${params.postId}?preview=${!!search.preview}`).then(r => r.json())
)
if (!post.published && !search.preview) throw redirect({ to: '/drafts' })
return { post }
},
})- 类型安全参数与搜索:自动推断路径参数;添加
createFileRoute()(zod)来解析和转换搜索参数。validateSearch - 路由匹配顺序确定(索引路由 → 静态路由 → 动态路由 → 通配路由);添加兜底路由时可依赖此规则。
- 加载器(Loader)在每次路径变更时运行一次;返回纯数据,通过抛出/
redirect()实现控制流。notFound() - 数据变更:将/服务端函数与组件同目录存放;保持加载器只读,变更后通过
action使缓存失效。router.invalidate() - TanStack Query桥接:在路由上下文中创建,并在加载器内使用
QueryClient来避免重复请求。ensureQueryData - 延迟/外部数据:流式传输部分数据或从外部加载器读取;优先选择支持Suspense的响应。
- 头部管理:为每个路由设置来配置
head/元信息;从加载器数据中派生,保持SEO一致性。<title> - 未找到/认证处理:在加载器/中间件中抛出或
notFound();使用错误边界优化用户体验。redirect()
示例路由(类型化搜索 + 仅数据SSR):
ts
// app/routes/posts.$postId.tsx
import { createFileRoute, redirect } from '@tanstack/react-router'
import { z } from 'zod'
export const Route = createFileRoute('/posts/$postId')({
validateSearch: z.object({ preview: z.boolean().optional() }),
ssr: 'data-only',
loader: async ({ params, search, context }) => {
const post = await context.queryClient.ensureQueryData(['post', params.postId], () =>
fetch(`/api/posts/${params.postId}?preview=${!!search.preview}`).then(r => r.json())
)
if (!post.published && !search.preview) throw redirect({ to: '/drafts' })
return { post }
},
})Navigation, Preloading, and UX
导航、预加载与用户体验
- Link prefetch defaults: (hover/focus) preloads route data/code; use
<Link preload="intent">for above-the-fold routes.preload="render" - Programmatic preloading: to warm caches before navigation (e.g., on visibility).
router.preloadRoute({ to, search }) - Route masking: keep canonical URLs while showing user-friendly masks (e.g., masked as
/products?slug=abc)./p/abc - Navigation blocking: protect unsaved forms with blockers or
router.navigate({ to, replace, from }).useBlocker - Scroll restoration: enable to restore positions on back/forward; customize per route when using long lists.
scrollRestoration - Search param serialization: customize parse/stringify to keep numbers/dates stable and avoid stringified booleans.
- 链接预加载默认配置:( hover/聚焦时)预加载路由数据/代码;首屏路由使用
<Link preload="intent">。preload="render" - 程序化预加载:使用在导航前预热缓存(例如元素可见时)。
router.preloadRoute({ to, search }) - 路由掩码:保留规范URL的同时显示用户友好的掩码(如显示为
/products?slug=abc)。/p/abc - 导航拦截:使用拦截器或
router.navigate({ to, replace, from })保护未保存的表单。useBlocker - 滚动恢复:启用来在前进/后退时恢复滚动位置;长列表场景可按路由自定义配置。
scrollRestoration - 搜索参数序列化:自定义解析/序列化逻辑,保持数字/日期稳定,避免布尔值被字符串化。
Rendering & Performance
渲染与性能
- Per-route SSR: set on routes;
ssr: true | false | 'data-only'config sets the baseline.defaultSsr - Code-splitting: file-based routes auto-split; add /
lazyfor manual chunks on code-based routes.load - Preloading strategy: pair links with
preload="intent"to avoid over-fetching.defaultPreloadStaleTime - Render optimizations: keep loaders pure, memoize heavy components, and use for CSR routes to avoid layout shift.
pendingComponent
- 按路由配置SSR:在路由上设置;
ssr: true | false | 'data-only'配置设置全局基准。defaultSsr - 代码分割:文件式路由自动分割;基于代码的路由可添加/
lazy手动拆分代码块。load - 预加载策略:将链接与
preload="intent"配合使用,避免过度请求。defaultPreloadStaleTime - 渲染优化:保持加载器纯函数化,缓存重型组件,CSR路由使用避免布局偏移。
pendingComponent
Devtools, Linting, and LLM Support
开发工具、代码检查与LLM支持
- Add during development to inspect matches, loader states, and preloading.
<RouterDevtools /> - Enable the ESLint plugin with the recommended config to enforce inference-sensitive property order (e.g.,
@tanstack/eslint-plugin-routerbeforebeforeLoad).loader - LLM-aware routing: the Router exposes structured route metadata to LLM agents; keep descriptions concise in meta for better AI navigation.
Route
- 开发期间添加来检查路由匹配、加载器状态和预加载情况。
<RouterDevtools /> - 启用ESLint插件并使用推荐配置,强制遵循对类型推断敏感的属性顺序(如
@tanstack/eslint-plugin-router在beforeLoad之前)。loader - LLM感知路由:Router向LLM Agent暴露结构化路由元数据;在元信息中保持描述简洁,以提升AI导航效果。
Route
Deployment Notes (Cloudflare-friendly)
部署注意事项(适配Cloudflare)
- Keep first in Vite plugins so bindings reach server entry.
cloudflare({ viteEnvironment: { name: 'ssr' } }) - Regenerate bindings after changes: .
npm run cf-typegen - For static-heavy sites, enable prerender to ship HTML to Workers Assets/Pages; exclude param routes or add explicit .
pages
- 在Vite插件中优先配置,确保绑定能传递到服务端入口。
cloudflare({ viteEnvironment: { name: 'ssr' } }) - 修改绑定后重新生成类型:。
npm run cf-typegen - 对于静态内容较多的站点,启用预渲染将HTML部署到Workers Assets/Pages;排除参数路由或添加明确的配置。
pages
Ship Checklist
发布检查清单
- Routes load without hydration warnings (prefer for non-deterministic UI).
ssr: 'data-only' - Search params validated with and custom serializer where needed.
validateSearch - Link preloading configured for high-traffic routes; blockers added for unsaved forms.
- ESLint plugin enabled (rule) and
create-route-property-orderpasses.npm run check - Devtools verified locally; state looks correct.
router.matches - Cloudflare bindings typed () and streaming tested via
cf-typegen.curl -N
- 路由加载无hydration警告(非确定性UI优先使用)。
ssr: 'data-only' - 搜索参数已通过验证,必要时使用自定义序列化器。
validateSearch - 高流量路由已配置链接预加载;未保存表单已添加拦截器。
- 已启用ESLint插件(规则),且
create-route-property-order通过。npm run check - 本地已验证开发工具;状态正常。
router.matches - Cloudflare绑定已生成类型(),并通过
cf-typegen测试流式传输。curl -N