关于 tanstack-start
TanStack Start 是基于 TanStack Router 的全栈 React 框架,面向构建服务端渲染应用的开发者。它集成流式 SSR、类型安全的服务端函数、中间件和 API 路由,并通过 Nitro 预设部署。
主要功能
- 01服务端渲染与流式响应
- 02类型安全的服务端 RPC 函数
- 03可组合的中间件
- 04文件式 API 路由
- 05通过 Nitro 预设部署
适用场景
- 01构建服务端渲染的 React 应用
- 02实现客户端与服务端的类型安全调用
- 03为路由配置身份验证中间件
- 04创建应用 API 端点
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tanstack-skills/ tanstack-skills --skill tanstack-start安装后在 Claude Code 中输入/tanstack-start确认已加载。
详细介绍
TanStack Start 技能
概述
TanStack Start 是一个基于 TanStack Router 构建的全栈 React 框架,由 Vite 和 Nitro(通过 Vinxi)提供支持。它提供服务器端渲染、流式传输、服务器函数(RPC)、中间件、API 路由,并可通过 Nitro 预设部署到任何平台。
包: @tanstack/react-start
路由插件: @tanstack/router-plugin
构建工具: Vinxi(Vite + Nitro)
状态: RC(候选发布版)
RSC 支持: React Server Components 支持正在积极开发中,并将作为非破坏性 v1.x 补充内容推出
安装与项目设置
npx @tanstack/cli create my-app
# Or manually:
npm install @tanstack/react-start @tanstack/react-router react react-dom
npm install -D @tanstack/router-plugin typescript vite vite-tsconfig-paths
项目结构
my-app/
app/
routes/
__root.tsx # Root layout
index.tsx # / route
posts.$postId.tsx # /posts/:postId
api/
users.ts # /api/users API route
client.tsx # Client entry
router.tsx # Router creation
ssr.tsx # SSR entry
routeTree.gen.ts # Auto-generated route tree
app.config.ts # TanStack Start config
tsconfig.json
package.json
配置(app.config.ts)
import { defineConfig } from '@tanstack/react-start/config'
import viteTsConfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
vite: {
plugins: [
viteTsConfigPaths({ projects: ['./tsconfig.json'] }),
],
},
server: {
preset: 'node-server', // 'vercel' | 'netlify' | 'cloudflare-pages' | etc.
},
tsr: {
appDirectory: './app',
routesDirectory: './app/routes',
generatedRouteTree: './app/routeTree.gen.ts',
},
})
服务器函数(createServerFn)
服务器函数在客户端和服务器之间提供类型安全的 RPC 调用。
基本服务器函数
import { createServerFn } from '@tanstack/react-start'
// GET (data fetching, cacheable)
const getUsers = createServerFn()
.handler(async () => {
const users = await db.query.users.findMany()
return users
})
// POST (mutations, side effects)
const createUser = createServerFn({ method: 'POST' })
.validator((data: { name: string; email: string }) => data)
.handler(async ({ data }) => {
const user = await db.insert(users).values(data).returning()
return user
})
使用 Zod 验证
import { z } from 'zod'
const updateUser = createServerFn({ method: 'POST' })
.validator(
z.object({
id: z.string(),
name: z.string().min(1),
email: z.string().email(),
})
)
.handler(async ({ data }) => {
// data is fully typed: { id: string; name: string; email: string }
return await db.update(users).set(data).where(eq(users.id, data.id))
})
中间件
创建中间件
import { createMiddleware } from '@tanstack/react-start'
const loggingMiddleware = createMiddleware().handler(async ({ next }) => {
console.log('Request started')
const result = await next()
console.log('Request completed')
return result
})
使用上下文的身份验证中间件
const authMiddleware = createMiddleware().handler(async ({ next }) => {
const request = getWebRequest()
const session = await getSession(request)
if (!session?.user) {
throw redirect({ to: '/login' })
}
// Pass typed context to handler
return next({ context: { user: session.user } })
})
链式中间件
const adminMiddleware = createMiddleware()
.middleware([authMiddleware])
.handler(async ({ next, context }) => {
// context.user is typed from authMiddleware
if (context.user.role !== 'admin') {
throw redirect({ to: '/unauthorized' })
}
return next({ context: { isAdmin: true } })
})
// Usage
const adminAction = createServerFn({ method: 'POST' })
.middleware([adminMiddleware])
.handler(async ({ context }) => {
// context: { user: User; isAdmin: boolean }
return { success: true }
})
API 路由(服务器路由)
// app/routes/api/users.ts
import { createAPIFileRoute } from '@tanstack/react-start/api'
export const APIRoute = createAPIFileRoute('/api/users')({
GET: async ({ request }) => {
const users = await db.query.users.findMany()
return Response.json(users)
},
POST: async ({ request }) => {
const body = await request.json()
const user = await db.insert(users).values(body).returning()
return new Response(JSON.stringify(user), { status: 201 })
},
})
SSR 策略
流式 SSR(默认)
export const Route = createFileRoute('/dashboard')({
loader: async () => ({
criticalData: await fetchCriticalData(),
deferredData: defer(fetchSlowData()),
}),
component: Dashboard,
})
function Dashboard() {
const { criticalData, deferredData } = Route.useLoaderData()
return (
<div>
<CriticalSection data={criticalData} />
<Suspense fallback={<Loading />}>
<Await promise={deferredData}>
{(data) => <SlowSection data={data} />}
</Await>
</Suspense>
</div>
)
}
部署
支持的平台(Nitro 预设)
// app.config.ts
export default defineConfig({
server: {
preset: 'node-server', // Self-hosted Node.js
// preset: 'vercel', // Vercel
// preset: 'netlify', // Netlify
// preset: 'cloudflare-pages', // Cloudflare Pages
// preset: 'aws-lambda', // AWS Lambda
// preset: 'deno-server', // Deno Deploy
// preset: 'bun', // Bun
},
})
最佳实践
- 为所有服务器函数输入使用验证器 - 确保运行时安全并推断 TypeScript 类型
- 组合中间件,处理横切关注点(身份验证、日志记录、速率限制)
- 数据获取使用
createServerFnGET(可缓存、可预加载) - 更改和副作用使用
createServerFnPOST - 使用
beforeLoad实现路由级身份验证守卫 - 使用
defer()处理非关键数据,以改善 TTFB - 在路由器上设置
defaultPreload: 'intent',实现即时导航 - 将服务器函数与使用它们的路由放在一起
常见问题
- 服务器函数无法闭包捕获客户端变量(这些函数会被提取到单独的代码包中)
- 服务器函数返回的数据必须可序列化
- 加载器中忘记使用
await会导致流式传输问题 - 在客户端代码包中导入仅限服务器端的代码会导致构建错误
- 缺少
declare module '@tanstack/react-router'会失去所有类型安全保障
评论
支持 Markdown