tanstack-start
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTanStack Start
TanStack Start
Full-stack React framework powered by TanStack Router and Vite. Adds SSR, streaming, server functions, middleware, server routes, and universal deployment to TanStack Router's type-safe routing.
TanStack Start is in Release Candidate stage. API is stable and feature-complete. No RSC support yet (in active development).
基于TanStack Router和Vite的全栈React框架。为TanStack Router的类型安全路由添加了SSR、流式传输、服务器函数、中间件、服务器路由以及通用部署能力。
TanStack Start处于候选发布阶段。API已稳定且功能完整,目前暂不支持RSC(正在积极开发中)。
When to Use This Skill
何时使用该工具
- Building full-stack React with SSR, SSG, or streaming
- Adding server functions (type-safe RPCs) to a React app
- Creating API/server routes alongside frontend routes
- Implementing middleware for auth, logging, or request handling
- Deploying to Cloudflare Workers, Netlify, Vercel, Node.js, Bun, or Docker
- Need SPA mode with optional server functions (no SSR required)
Use TanStack Router alone (see tanstack-router skill) when you only need client-side routing without server features.
For routing concepts (file-based routing, search params, nested layouts, loaders, preloading), refer to the tanstack-router skill. This skill covers Start-specific full-stack features.
- 构建支持SSR、SSG或流式传输的全栈React应用
- 为React应用添加服务器函数(类型安全RPC)
- 与前端路由一同创建API/服务器路由
- 实现用于认证、日志或请求处理的中间件
- 部署至Cloudflare Workers、Netlify、Vercel、Node.js、Bun或Docker环境
- 需要带可选服务器函数的SPA模式(无需SSR)
仅使用TanStack Router(参考tanstack-router工具):当你只需要客户端路由,不需要服务器端功能时。
关于路由概念(基于文件的路由、搜索参数、嵌套布局、加载器、预加载),请参考tanstack-router工具。本工具仅涵盖Start特有的全栈功能。
Quick Start Workflow
快速开始流程
1. Create Project
1. 创建项目
bash
pnpm create @tanstack/start@latestbash
pnpm create @tanstack/start@latest2. Manual Setup
2. 手动搭建
bash
npm i @tanstack/react-start @tanstack/react-router react react-dom
npm i -D vite @vitejs/plugin-react typescript @types/react @types/react-dom vite-tsconfig-pathsbash
npm i @tanstack/react-start @tanstack/react-router react react-dom
npm i -D vite @vitejs/plugin-react typescript @types/react @types/react-dom vite-tsconfig-paths3. Vite Configuration
3. Vite配置
ts
// vite.config.ts
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
export default defineConfig({
server: { port: 3000 },
plugins: [
tsConfigPaths(),
tanstackStart(),
viteReact(), // MUST come after tanstackStart()
],
})ts
// vite.config.ts
import { defineConfig } from 'vite'
import tsConfigPaths from 'vite-tsconfig-paths'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
export default defineConfig({
server: { port: 3000 },
plugins: [
tsConfigPaths(),
tanstackStart(),
viteReact(), // 必须在tanstackStart()之后
],
})4. Router and Root Route
4. 路由与根路由
tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
return createRouter({ routeTree, scrollRestoration: true })
}tsx
// src/routes/__root.tsx
/// <reference types="vite/client" />
import type { ReactNode } from 'react'
import { Outlet, createRootRoute, HeadContent, Scripts } from '@tanstack/react-router'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My TanStack Start App' },
],
}),
component: () => (
<html>
<head><HeadContent /></head>
<body><Outlet /><Scripts /></body>
</html>
),
})tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
return createRouter({ routeTree, scrollRestoration: true })
}tsx
// src/routes/__root.tsx
/// <reference types="vite/client" />
import type { ReactNode } from 'react'
import { Outlet, createRootRoute, HeadContent, Scripts } from '@tanstack/react-router'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My TanStack Start App' },
],
}),
component: () => (
<html>
<head><HeadContent /></head>
<body><Outlet /><Scripts /></body>
</html>
),
})5. Route with Server Function
5. 带服务器函数的路由
tsx
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
const getServerTime = createServerFn({ method: 'GET' }).handler(async () => {
return new Date().toISOString()
})
export const Route = createFileRoute('/')({
loader: () => getServerTime(),
component: () => {
const time = Route.useLoaderData()
return <div>Server time: {time}</div>
},
})tsx
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
const getServerTime = createServerFn({ method: 'GET' }).handler(async () => {
return new Date().toISOString()
})
export const Route = createFileRoute('/')({
loader: () => getServerTime(),
component: () => {
const time = Route.useLoaderData()
return <div>Server time: {time}</div>
},
})File Structure
文件结构
src/
├── routes/
│ ├── __root.tsx # HTML shell, always rendered
│ └── index.tsx
├── router.tsx # Router config
├── routeTree.gen.ts # Auto-generated
├── start.ts # Optional: global middleware
└── server.ts # Optional: custom server entrysrc/
├── routes/
│ ├── __root.tsx # HTML外壳,始终会渲染
│ └── index.tsx
├── router.tsx # 路由配置
├── routeTree.gen.ts # 自动生成
├── start.ts # 可选:全局中间件
└── server.ts # 可选:自定义服务器入口Execution Model
执行模型
All code is isomorphic by default - runs in both server and client bundles unless constrained. Route s run on the server during SSR AND on the client during navigation.
loadertsx
// WRONG - secret exposed to client bundle
export const Route = createFileRoute('/users')({
loader: () => {
const secret = process.env.SECRET
return fetch(`/api/users?key=${secret}`)
},
})
// CORRECT - server function keeps secrets server-side
const getUsers = createServerFn().handler(async () => {
return fetch(`/api/users?key=${process.env.SECRET}`)
})
export const Route = createFileRoute('/users')({
loader: () => getUsers(),
})| API | Runs On | Client Behavior |
|---|---|---|
| Server | Network request (RPC) |
| Server | Throws error |
| Client | Works normally |
| Both | Environment-specific impl |
| Client | Renders fallback on server |
默认情况下,所有代码都是同构的——除非加以限制,否则会同时在服务器和客户端包中运行。路由的会在SSR期间在服务器上运行,也会在客户端导航时在客户端运行。
loadertsx
// 错误示例 - 密钥暴露给客户端包
export const Route = createFileRoute('/users')({
loader: () => {
const secret = process.env.SECRET
return fetch(`/api/users?key=${secret}`)
},
})
// 正确示例 - 服务器函数将密钥保留在服务器端
const getUsers = createServerFn().handler(async () => {
return fetch(`/api/users?key=${process.env.SECRET}`)
})
export const Route = createFileRoute('/users')({
loader: () => getUsers(),
})| API | 运行环境 | 客户端行为 |
|---|---|---|
| 服务器 | 网络请求(RPC) |
| 服务器 | 抛出错误 |
| 客户端 | 正常运行 |
| 两者 | 基于环境的特定实现 |
| 客户端 | 在服务器上渲染回退内容 |
Server Functions
服务器函数
Type-safe RPCs via . Server code is extracted from client bundles at build time; client calls become requests.
createServerFn()fetchtsx
import { createServerFn } from '@tanstack/react-start'
import { z } from 'zod'
import { redirect, notFound } from '@tanstack/react-router'
// GET with no input
export const getData = createServerFn({ method: 'GET' }).handler(async () => {
return { message: 'Hello from server!' }
})
// POST with Zod validation
const CreatePostSchema = z.object({
title: z.string().min(1).max(200),
body: z.string().min(1),
})
export const createPost = createServerFn({ method: 'POST' })
.inputValidator(CreatePostSchema)
.handler(async ({ data }) => {
return await db.posts.create(data)
})
// Redirect and notFound
export const getPost = createServerFn()
.inputValidator((data: { id: string }) => data)
.handler(async ({ data }) => {
const post = await db.findPost(data.id)
if (!post) throw notFound()
return post
})通过实现类型安全的RPC。构建时服务器代码会从客户端包中提取;客户端调用会变为请求。
createServerFn()fetchtsx
import { createServerFn } from '@tanstack/react-start'
import { z } from 'zod'
import { redirect, notFound } from '@tanstack/react-router'
// 无输入的GET请求
export const getData = createServerFn({ method: 'GET' }).handler(async () => {
return { message: 'Hello from server!' }
})
// 带Zod验证的POST请求
const CreatePostSchema = z.object({
title: z.string().min(1).max(200),
body: z.string().min(1),
})
export const createPost = createServerFn({ method: 'POST' })
.inputValidator(CreatePostSchema)
.handler(async ({ data }) => {
return await db.posts.create(data)
})
// 重定向与404处理
export const getPost = createServerFn()
.inputValidator((data: { id: string }) => data)
.handler(async ({ data }) => {
const post = await db.findPost(data.id)
if (!post) throw notFound()
return post
})Calling Server Functions
调用服务器函数
tsx
// From loader
export const Route = createFileRoute('/posts')({
loader: () => getPosts(),
})
// From component with useServerFn
import { useServerFn } from '@tanstack/react-start'
function CreatePostForm() {
const mutation = useServerFn(createPost)
return <button onClick={() => mutation({ data: { title: 'New', body: 'Content' } })}>Create</button>
}
// Direct call with router.invalidate()
function DeleteButton({ id }: { id: string }) {
const router = useRouter()
return <button onClick={() => deletePost({ data: { id } }).then(() => router.invalidate())}>Delete</button>
}tsx
// 从loader中调用
export const Route = createFileRoute('/posts')({
loader: () => getPosts(),
})
// 在组件中使用useServerFn调用
import { useServerFn } from '@tanstack/react-start'
function CreatePostForm() {
const mutation = useServerFn(createPost)
return <button onClick={() => mutation({ data: { title: 'New', body: 'Content' } })}>Create</button>
}
// 直接调用并结合router.invalidate()
function DeleteButton({ id }: { id: string }) {
const router = useRouter()
return <button onClick={() => deletePost({ data: { id } }).then(() => router.invalidate())}>Delete</button>
}Server Context Utilities
服务器上下文工具
Access request/response from : , , , .
@tanstack/react-start/servergetRequest()getRequestHeader(name)setResponseHeaders(headers)setResponseStatus(code)从访问请求/响应:、、、。
@tanstack/react-start/servergetRequest()getRequestHeader(name)setResponseHeaders(headers)setResponseStatus(code)Middleware
中间件
Two types: request middleware (all server requests including SSR) and server function middleware (server functions only, with client-side hooks and input validation).
分为两种类型:请求中间件(包括SSR在内的所有服务器请求)和服务器函数中间件(仅适用于服务器函数,带有客户端钩子和输入验证)。
Request Middleware
请求中间件
tsx
import { createMiddleware } from '@tanstack/react-start'
const loggingMiddleware = createMiddleware().server(async ({ next, request }) => {
const start = Date.now()
const result = await next()
console.log(`${request.method} ${request.url} - ${Date.now() - start}ms`)
return result
})tsx
import { createMiddleware } from '@tanstack/react-start'
const loggingMiddleware = createMiddleware().server(async ({ next, request }) => {
const start = Date.now()
const result = await next()
console.log(`${request.method} ${request.url} - ${Date.now() - start}ms`)
return result
})Server Function Middleware with Context
带上下文的服务器函数中间件
tsx
const authMiddleware = createMiddleware({ type: 'function' })
.server(async ({ next }) => {
const user = await getCurrentUser()
if (!user) throw redirect({ to: '/login' })
return next({ context: { user } })
})
const getProfile = createServerFn()
.middleware([authMiddleware])
.handler(async ({ context }) => {
return context.user // typed
})tsx
const authMiddleware = createMiddleware({ type: 'function' })
.server(async ({ next }) => {
const user = await getCurrentUser()
if (!user) throw redirect({ to: '/login' })
return next({ context: { user } })
})
const getProfile = createServerFn()
.middleware([authMiddleware])
.handler(async ({ context }) => {
return context.user // 已类型化
})Client + Server Middleware
客户端+服务器中间件
tsx
const authHeaderMiddleware = createMiddleware({ type: 'function' })
.client(async ({ next }) => {
return next({ headers: { Authorization: `Bearer ${getToken()}` } })
})
.server(async ({ next }) => {
const user = await verifyToken(getRequestHeader('Authorization'))
return next({ context: { user } })
})tsx
const authHeaderMiddleware = createMiddleware({ type: 'function' })
.client(async ({ next }) => {
return next({ headers: { Authorization: `Bearer ${getToken()}` } })
})
.server(async ({ next }) => {
const user = await verifyToken(getRequestHeader('Authorization'))
return next({ context: { user } })
})Global Middleware (src/start.ts)
全局中间件(src/start.ts)
tsx
import { createStart, createMiddleware } from '@tanstack/react-start'
export const startInstance = createStart(() => ({
requestMiddleware: [globalLogger], // ALL requests (SSR, routes, fns)
functionMiddleware: [globalAuth], // ALL server functions
}))tsx
import { createStart, createMiddleware } from '@tanstack/react-start'
export const startInstance = createStart(() => ({
requestMiddleware: [globalLogger], // 所有请求(SSR、路由、函数)
functionMiddleware: [globalAuth], // 所有服务器函数
}))Server Routes
服务器路由
HTTP endpoints alongside frontend routes using file-based routing. Handlers receive and return .
{ request, params, context }Responsetsx
// src/routes/api/users.ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/api/users')({
server: {
middleware: [authMiddleware],
handlers: {
GET: async ({ request }) => {
return Response.json(await db.users.findMany())
},
POST: async ({ request }) => {
const body = await request.json()
return Response.json(await db.users.create(body), { status: 201 })
},
},
},
})Per-handler middleware via :
createHandlerstsx
server: {
handlers: ({ createHandlers }) => createHandlers({
GET: async ({ request }) => Response.json({ ok: true }),
DELETE: {
middleware: [adminOnlyMiddleware],
handler: async ({ request }) => Response.json({ deleted: true }),
},
}),
}Server routes and components can co-exist in the same file. Dynamic params (), wildcards (), and escaped matching () all work identically to Router.
$id$[.]json通过基于文件的路由,在前端路由旁创建HTTP端点。处理器接收并返回。
{ request, params, context }Responsetsx
// src/routes/api/users.ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/api/users')({
server: {
middleware: [authMiddleware],
handlers: {
GET: async ({ request }) => {
return Response.json(await db.users.findMany())
},
POST: async ({ request }) => {
const body = await request.json()
return Response.json(await db.users.create(body), { status: 201 })
},
},
},
})通过为单个处理器添加中间件:
createHandlerstsx
server: {
handlers: ({ createHandlers }) => createHandlers({
GET: async ({ request }) => Response.json({ ok: true }),
DELETE: {
middleware: [adminOnlyMiddleware],
handler: async ({ request }) => Response.json({ deleted: true }),
},
}),
}服务器路由和组件可以共存于同一文件中。动态参数()、通配符()和转义匹配()的工作方式与Router完全相同。
$id$[.]jsonSSR Modes
SSR模式
Per-route SSR control via the property:
ssr| Mode | Loaders | Component | Use Case |
|---|---|---|---|
| Server + Client | Server + Client | SEO, performance |
| Client only | Client only | Browser APIs, canvas |
| Server + Client | Client only | Dashboards |
| Dynamic | Dynamic | Conditional SSR |
tsx
export const Route = createFileRoute('/dashboard')({
ssr: 'data-only',
loader: () => getDashboardData(),
component: Dashboard,
})通过属性按路由控制SSR:
ssr| 模式 | 加载器 | 组件 | 使用场景 |
|---|---|---|---|
| 服务器+客户端 | 服务器+客户端 | SEO、性能优化 |
| 仅客户端 | 仅客户端 | 浏览器API、画布应用 |
| 服务器+客户端 | 仅客户端 | 仪表盘应用 |
| 动态 | 动态 | 条件式SSR |
tsx
export const Route = createFileRoute('/dashboard')({
ssr: 'data-only',
loader: () => getDashboardData(),
component: Dashboard,
})SPA Mode
SPA模式
Ship static HTML shells with server function support but no SSR:
ts
// vite.config.ts
tanstackStart({ spa: { enabled: true } })交付静态HTML外壳,支持服务器函数但无SSR:
ts
// vite.config.ts
tanstackStart({ spa: { enabled: true } })Global Default
全局默认设置
tsx
// src/start.ts
export const startInstance = createStart(() => ({ defaultSsr: false }))tsx
// src/start.ts
export const startInstance = createStart(() => ({ defaultSsr: false }))Head Management and SEO
头部管理与SEO
tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => ({ post: await getPost({ data: { id: params.postId } }) }),
head: ({ loaderData }) => ({
meta: [
{ title: loaderData.post.title },
{ name: 'description', content: loaderData.post.excerpt },
{ property: 'og:title', content: loaderData.post.title },
{ property: 'og:image', content: loaderData.post.coverImage },
{ name: 'twitter:card', content: 'summary_large_image' },
],
links: [{ rel: 'canonical', href: `https://myapp.com/posts/${loaderData.post.id}` }],
}),
component: PostPage,
})tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => ({ post: await getPost({ data: { id: params.postId } }) }),
head: ({ loaderData }) => ({
meta: [
{ title: loaderData.post.title },
{ name: 'description', content: loaderData.post.excerpt },
{ property: 'og:title', content: loaderData.post.title },
{ property: 'og:image', content: loaderData.post.coverImage },
{ name: 'twitter:card', content: 'summary_large_image' },
],
links: [{ rel: 'canonical', href: `https://myapp.com/posts/${loaderData.post.id}` }],
}),
component: PostPage,
})Authentication
认证
Session Management
会话管理
tsx
// utils/session.ts
import { useSession } from '@tanstack/react-start/server'
export function useAppSession() {
return useSession<{ userId?: string; email?: string }>({
name: 'app-session',
password: process.env.SESSION_SECRET!,
cookie: { secure: process.env.NODE_ENV === 'production', sameSite: 'lax', httpOnly: true },
})
}tsx
// utils/session.ts
import { useSession } from '@tanstack/react-start/server'
export function useAppSession() {
return useSession<{ userId?: string; email?: string }>({
name: 'app-session',
password: process.env.SESSION_SECRET!,
cookie: { secure: process.env.NODE_ENV === 'production', sameSite: 'lax', httpOnly: true },
})
}Route Protection
路由保护
tsx
// src/routes/_authed.tsx - layout route guard
export const Route = createFileRoute('/_authed')({
beforeLoad: async ({ location }) => {
const user = await getCurrentUserFn()
if (!user) throw redirect({ to: '/login', search: { redirect: location.href } })
return { user }
},
})
// src/routes/_authed/dashboard.tsx - automatically protected
export const Route = createFileRoute('/_authed/dashboard')({
component: () => {
const { user } = Route.useRouteContext()
return <h1>Welcome, {user.email}!</h1>
},
})tsx
// src/routes/_authed.tsx - 布局路由守卫
export const Route = createFileRoute('/_authed')({
beforeLoad: async ({ location }) => {
const user = await getCurrentUserFn()
if (!user) throw redirect({ to: '/login', search: { redirect: location.href } })
return { user }
},
})
// src/routes/_authed/dashboard.tsx - 自动受保护
export const Route = createFileRoute('/_authed/dashboard')({
component: () => {
const { user } = Route.useRouteContext()
return <h1>Welcome, {user.email}!</h1>
},
})Environment Functions
环境函数
tsx
import { createIsomorphicFn, createServerOnlyFn, createClientOnlyFn } from '@tanstack/react-start'
import { ClientOnly } from '@tanstack/react-router'
const getDeviceInfo = createIsomorphicFn()
.server(() => ({ type: 'server', platform: process.platform }))
.client(() => ({ type: 'client', userAgent: navigator.userAgent }))
const getDbUrl = createServerOnlyFn(() => process.env.DATABASE_URL) // throws on client
const saveLocal = createClientOnlyFn((k: string, v: string) => localStorage.setItem(k, v)) // throws on server
// Component-level: renders fallback during SSR, children after hydration
<ClientOnly fallback={<div>Loading...</div>}><InteractiveChart /></ClientOnly>tsx
import { createIsomorphicFn, createServerOnlyFn, createClientOnlyFn } from '@tanstack/react-start'
import { ClientOnly } from '@tanstack/react-router'
const getDeviceInfo = createIsomorphicFn()
.server(() => ({ type: 'server', platform: process.platform }))
.client(() => ({ type: 'client', userAgent: navigator.userAgent }))
const getDbUrl = createServerOnlyFn(() => process.env.DATABASE_URL) // 在客户端会抛出错误
const saveLocal = createClientOnlyFn((k: string, v: string) => localStorage.setItem(k, v)) // 在服务器会抛出错误
// 组件层面:SSR期间渲染回退内容, hydration后渲染子组件
<ClientOnly fallback={<div>Loading...</div>}><InteractiveChart /></ClientOnly>Deployment
部署
Cloudflare Workers (Official Partner)
Cloudflare Workers(官方合作伙伴)
Install and , add to vite plugins (before ), and set in .
@cloudflare/vite-pluginwranglercloudflare({ viteEnvironment: { name: 'ssr' } })tanstackStart()"main": "@tanstack/react-start/server-entry"wrangler.jsonc安装和,在vite插件中添加(在之前),并在中设置。
@cloudflare/vite-pluginwranglercloudflare({ viteEnvironment: { name: 'ssr' } })tanstackStart()wrangler.jsonc"main": "@tanstack/react-start/server-entry"Netlify (Official Partner)
Netlify(官方合作伙伴)
Install , add to vite plugins alongside .
@netlify/vite-plugin-tanstack-startnetlify()tanstackStart()安装,在vite插件中添加与一同使用。
@netlify/vite-plugin-tanstack-startnetlify()tanstackStart()Nitro (Node.js, Vercel, Bun, Docker)
Nitro(Node.js、Vercel、Bun、Docker)
Install , add to vite plugins. Build with , run with .
nitro@npm:nitro-nightly@latestnitro()vite buildnode .output/server/index.mjs安装,在vite插件中添加。使用构建,运行。
nitro@npm:nitro-nightly@latestnitro()vite buildnode .output/server/index.mjsStatic Prerendering
静态预渲染
ts
tanstackStart({ prerender: { enabled: true, crawlLinks: true } })ts
tanstackStart({ prerender: { enabled: true, crawlLinks: true } })Best Practices
最佳实践
- Never put secrets in loaders - Loaders are isomorphic. Use for server-only access.
createServerFn() - Server functions are the boundary - Primary mechanism for safe server-only execution from client code.
- Organize by concern - for server fn wrappers,
.functions.tsfor internal helpers,.server.tsfor shared types/schemas..ts - Compose middleware hierarchically - Global for cross-cutting concerns, route-level for groups, function-level for specifics.
- Use on every content route - Title, description, OG tags. Use loader data for dynamic pages.
head() - Choose SSR mode per route - for SEO,
truefor browser-only,falsefor dashboards.'data-only' - Validate all server function inputs - Zod or custom validators via .
.inputValidator()
- 切勿在loader中存放密钥 - Loader是同构的。使用实现仅服务器端访问。
createServerFn() - 服务器函数是安全边界 - 从客户端代码安全执行仅服务器端逻辑的主要机制。
- 按关注点组织代码 - 用于服务器函数封装,
.functions.ts用于内部工具,.server.ts用于共享类型/模式。.ts - 分层组合中间件 - 全局中间件用于跨领域关注点,路由级用于分组,函数级用于特定场景。
- 在每个内容路由中使用- 设置标题、描述、OG标签。使用loader数据处理动态页面。
head() - 为每个路由选择合适的SSR模式 - 用于SEO,
true用于仅浏览器应用,false用于仪表盘。'data-only' - 验证所有服务器函数输入 - 通过使用Zod或自定义验证器。
.inputValidator()
Advanced Topics
进阶主题
For deeper coverage, see reference files:
- - Streaming, FormData, progressive enhancement, request cancellation, custom function IDs
references/server-functions.md - - sendContext, custom fetch, global config, environment tree shaking
references/middleware.md - - Selective SSR inheritance, functional form, shellComponent, fallback rendering
references/ssr-modes.md - - Dynamic params, wildcards, escaped matching, pathless layouts
references/server-routes.md
如需深入了解,请参考以下参考文件:
- - 流式传输、FormData、渐进式增强、请求取消、自定义函数ID
references/server-functions.md - - sendContext、自定义fetch、全局配置、环境树摇
references/middleware.md - - 选择性SSR继承、函数形式、shellComponent、回退渲染
references/ssr-modes.md - - 动态参数、通配符、转义匹配、无路径布局
references/server-routes.md
Resources
资源
- Official Docs
- GitHub (Start lives in the router repo)
- Examples - Basic, Auth, React Query, Cloudflare, Clerk, Supabase
- Start vs Next.js
- Cross-reference: tanstack-router skill for routing, tanstack-query skill for data fetching
- 官方文档
- GitHub(Start位于router仓库中)
- 示例 - 基础示例、认证、React Query、Cloudflare、Clerk、Supabase
- Start vs Next.js
- 交叉参考:tanstack-router工具用于路由,tanstack-query工具用于数据获取