tanstack-start

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TanStack 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:
    scripts/bootstrap-cloudflare-start.sh <app>
    scaffolds Start + Workers + binding types.
  • Troubleshooting: hydration, API routing, bindings, navigation/preloading failures.

  • 参考文档:快速入门/布局、渲染模式、服务端函数、Cloudflare托管、执行/认证,以及新增的路由/数据/导航/开发工具指南。
  • 脚本
    scripts/bootstrap-cloudflare-start.sh <app>
    可快速搭建Start + Workers + 绑定类型的项目。
  • 故障排查:hydration、API路由、绑定、导航/预加载失败问题的解决方法。

Quick Start (React)

快速开始(React)

bash
npm create @tanstack/start@latest my-app
cd my-app
npm run dev
Manual installs (all bundle targets are supported): add
@tanstack/react-router
+
@tanstack/react-start
with your bundler plugin (
vite
,
webpack
, or
esbuild
) per the official install guides.
bash
npm create @tanstack/start@latest my-app
cd my-app
npm run dev
手动安装(支持所有打包工具):根据官方安装指南,添加
@tanstack/react-router
+
@tanstack/react-start
,并配置对应的打包器插件(
vite
webpack
esbuild
)。

Core layout reminder

核心布局提示

  • app/routes/**
    file-based routes → router tree, automatic code-splitting + data preloading.
  • app/entry.client.tsx
    hydrates
    <StartClient />
    ;
    app/entry.server.tsx
    wraps
    createServerEntry
    .
  • app/config.ts
    or
    app/start.ts
    sets
    defaultSsr
    ,
    spaMode
    , middleware, and context.

  • 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:
    createFileRoute()
    infers path params; add
    validateSearch
    (zod) to parse and coerce search params.
  • 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()
    /
    notFound()
    for control flow.
  • Data mutations: colocate
    action
    /server functions; keep loaders read-only and invalidate via
    router.invalidate()
    after mutation.
  • TanStack Query bridge: create a
    QueryClient
    in router context and
    ensureQueryData
    inside loaders to dedupe fetches.
  • Deferred/external data: stream partial data or read from external loaders; prefer suspense-friendly responses.
  • Head management: set
    head
    per route for
    <title>
    /meta; derive from loader data to keep SEO consistent.
  • Not-found/auth: throw
    notFound()
    or
    redirect()
    in loaders/middleware; use error boundaries for UX.
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()
    自动推断路径参数;添加
    validateSearch
    (zod)来解析和转换搜索参数。
  • 路由匹配顺序确定(索引路由 → 静态路由 → 动态路由 → 通配路由);添加兜底路由时可依赖此规则。
  • 加载器(Loader)在每次路径变更时运行一次;返回纯数据,通过抛出
    redirect()
    /
    notFound()
    实现控制流。
  • 数据变更:将
    action
    /服务端函数与组件同目录存放;保持加载器只读,变更后通过
    router.invalidate()
    使缓存失效。
  • TanStack Query桥接:在路由上下文中创建
    QueryClient
    ,并在加载器内使用
    ensureQueryData
    来避免重复请求。
  • 延迟/外部数据:流式传输部分数据或从外部加载器读取;优先选择支持Suspense的响应。
  • 头部管理:为每个路由设置
    head
    来配置
    <title>
    /元信息;从加载器数据中派生,保持SEO一致性。
  • 未找到/认证处理:在加载器/中间件中抛出
    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:
    <Link preload="intent">
    (hover/focus) preloads route data/code; use
    preload="render"
    for above-the-fold routes.
  • Programmatic preloading:
    router.preloadRoute({ to, search })
    to warm caches before navigation (e.g., on visibility).
  • Route masking: keep canonical URLs while showing user-friendly masks (e.g.,
    /products?slug=abc
    masked as
    /p/abc
    ).
  • Navigation blocking: protect unsaved forms with
    router.navigate({ to, replace, from })
    blockers or
    useBlocker
    .
  • Scroll restoration: enable
    scrollRestoration
    to restore positions on back/forward; customize per route when using long lists.
  • Search param serialization: customize parse/stringify to keep numbers/dates stable and avoid stringified booleans.

  • 链接预加载默认配置
    <Link preload="intent">
    ( hover/聚焦时)预加载路由数据/代码;首屏路由使用
    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
    ssr: true | false | 'data-only'
    on routes;
    defaultSsr
    config sets the baseline.
  • Code-splitting: file-based routes auto-split; add
    lazy
    /
    load
    for manual chunks on code-based routes.
  • Preloading strategy: pair
    preload="intent"
    links with
    defaultPreloadStaleTime
    to avoid over-fetching.
  • Render optimizations: keep loaders pure, memoize heavy components, and use
    pendingComponent
    for CSR routes to avoid layout shift.

  • 按路由配置SSR:在路由上设置
    ssr: true | false | 'data-only'
    defaultSsr
    配置设置全局基准。
  • 代码分割:文件式路由自动分割;基于代码的路由可添加
    lazy
    /
    load
    手动拆分代码块。
  • 预加载策略:将
    preload="intent"
    链接与
    defaultPreloadStaleTime
    配合使用,避免过度请求。
  • 渲染优化:保持加载器纯函数化,缓存重型组件,CSR路由使用
    pendingComponent
    避免布局偏移。

Devtools, Linting, and LLM Support

开发工具、代码检查与LLM支持

  • Add
    <RouterDevtools />
    during development to inspect matches, loader states, and preloading.
  • Enable the ESLint plugin
    @tanstack/eslint-plugin-router
    with the recommended config to enforce inference-sensitive property order (e.g.,
    beforeLoad
    before
    loader
    ).
  • LLM-aware routing: the Router exposes structured route metadata to LLM agents; keep descriptions concise in
    Route
    meta for better AI navigation.

  • 开发期间添加
    <RouterDevtools />
    来检查路由匹配、加载器状态和预加载情况。
  • 启用ESLint插件
    @tanstack/eslint-plugin-router
    并使用推荐配置,强制遵循对类型推断敏感的属性顺序(如
    beforeLoad
    loader
    之前)。
  • LLM感知路由:Router向LLM Agent暴露结构化路由元数据;在
    Route
    元信息中保持描述简洁,以提升AI导航效果。

Deployment Notes (Cloudflare-friendly)

部署注意事项(适配Cloudflare)

  • Keep
    cloudflare({ viteEnvironment: { name: 'ssr' } })
    first in Vite plugins so bindings reach server entry.
  • 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
    ssr: 'data-only'
    for non-deterministic UI).
  • Search params validated with
    validateSearch
    and custom serializer where needed.
  • Link preloading configured for high-traffic routes; blockers added for unsaved forms.
  • ESLint plugin enabled (
    create-route-property-order
    rule) and
    npm run check
    passes.
  • Devtools verified locally;
    router.matches
    state looks correct.
  • Cloudflare bindings typed (
    cf-typegen
    ) and streaming tested via
    curl -N
    .
  • 路由加载无hydration警告(非确定性UI优先使用
    ssr: 'data-only'
    )。
  • 搜索参数已通过
    validateSearch
    验证,必要时使用自定义序列化器。
  • 高流量路由已配置链接预加载;未保存表单已添加拦截器。
  • 已启用ESLint插件(
    create-route-property-order
    规则),且
    npm run check
    通过。
  • 本地已验证开发工具;
    router.matches
    状态正常。
  • Cloudflare绑定已生成类型(
    cf-typegen
    ),并通过
    curl -N
    测试流式传输。