字
字节笔记本
2026年5月3日
TanStack Start - Server Functions 服务端函数
API中转
¥120
TanStack Start 的服务端函数让你定义仅在服务端运行的逻辑,可以从应用的任何地方调用,保持类型安全。
什么是 Server Functions
服务端函数让你定义仅在服务端运行的逻辑,可以从应用的任何地方调用 - loaders、组件、hooks 或其他服务端函数。它们在服务端运行,但可以从客户端代码无缝调用。
tsx
import { createServerFn } from '@tanstack/react-start'
export const getServerTime = createServerFn().handler(async () => {
// 仅在服务端运行
return new Date().toISOString()
})
// 从任何地方调用 - 组件、loaders、hooks 等
const time = await getServerTime()服务端函数提供服务端能力(数据库访问、环境变量、文件系统),同时跨网络边界保持类型安全。
基础用法
服务端函数使用 createServerFn() 创建,可以指定 HTTP 方法:
tsx
import { createServerFn } from '@tanstack/react-start'
// GET 请求(默认)
export const getData = createServerFn().handler(async () => {
return { message: 'Hello from server!' }
})
// POST 请求
export const saveData = createServerFn({ method: 'POST' }).handler(async () => {
return { success: true }
})在哪里调用 Server Functions
可以从以下位置调用服务端函数:
- Route loaders - 数据获取的最佳选择
- Components - 使用
useServerFn()hook - Other server functions - 组合服务端逻辑
- Event handlers - 处理表单提交、点击等
tsx
// 在路由 loader 中
export const Route = createFileRoute('/posts')({
loader: () => getPosts(),
})
// 在组件中
function PostList() {
const getPosts = useServerFn(getServerPosts)
const { data } = useQuery({
queryKey: ['posts'],
queryFn: () => getPosts(),
})
}文件组织
对于大型应用,建议将服务端代码组织到独立文件中:
text
src/utils/
├── users.functions.ts # Server function 包装器 (createServerFn)
├── users.server.ts # 仅服务端助手 (DB 查询、内部逻辑)
└── schemas.ts # 共享验证模式 (客户端安全)文件类型说明
| 后缀 | 用途 | 导入位置 |
|---|---|---|
.functions.ts | 导出 createServerFn 包装器 | 任何地方安全 |
.server.ts | 仅服务端代码 | 仅在服务端函数 handler 内 |
.ts (无后缀) | 客户端安全代码(类型、模式、常量) | 任何地方 |
静态导入是安全的
服务端函数可以在任何文件中静态导入,包括客户端组件:
tsx
import { getUser } from '~/utils/users.functions'
function UserProfile({ id }) {
const { data } = useQuery({
queryKey: ['user', id],
queryFn: () => getUser({ data: { id } }),
})
}构建过程将服务端函数实现替换为客户端 bundle 中的 RPC 存根。实际服务端代码永远不会到达浏览器。
参数与验证
服务端函数接受单个 data 参数。由于跨网络边界,验证确保类型安全和运行时正确性。
基础参数
tsx
export const greetUser = createServerFn({ method: 'GET' })
.inputValidator((data: { name: string }) => data)
.handler(async ({ data }) => {
return `Hello, ${data.name}!`
})
await greetUser({ data: { name: 'John' } })使用 Zod 验证
tsx
import { z } from 'zod'
const UserSchema = z.object({
name: z.string().min(1),
age: z.number().min(0),
})
export const createUser = createServerFn({ method: 'POST' })
.inputValidator(UserSchema)
.handler(async ({ data }) => {
return `Created user: ${data.name}, age ${data.age}`
})FormData 处理
tsx
export const submitForm = createServerFn({ method: 'POST' })
.inputValidator((data) => {
if (!(data instanceof FormData)) {
throw new Error('Expected FormData')
}
return {
name: data.get('name')?.toString() || '',
email: data.get('email')?.toString() || '',
}
})
.handler(async ({ data }) => {
return { success: true }
})错误处理与重定向
基础错误
tsx
export const riskyFunction = createServerFn().handler(async () => {
if (Math.random() > 0.5) {
throw new Error('Something went wrong!')
}
return { success: true }
})重定向
tsx
import { redirect } from '@tanstack/react-router'
export const requireAuth = createServerFn().handler(async () => {
const user = await getCurrentUser()
if (!user) {
throw redirect({ to: '/login' })
}
return user
})Not Found
tsx
import { notFound } from '@tanstack/react-router'
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
})高级主题
Server Context & Request Handling
tsx
import {
getRequest,
getRequestHeader,
setResponseHeaders,
setResponseStatus,
} from '@tanstack/react-start/server'
export const getCachedData = createServerFn({ method: 'GET' }).handler(
async () => {
const request = getRequest()
const authHeader = getRequestHeader('Authorization')
setResponseHeaders(
new Headers({
'Cache-Control': 'public, max-age=300',
'CDN-Cache-Control': 'max-age=3600, stale-while-revalidate=600',
}),
)
setResponseStatus(200)
return fetchData()
},
)可用工具
| 工具 | 用途 |
|---|---|
getRequest() | 访问完整 Request 对象 |
getRequestHeader(name) | 读取特定请求头 |
setResponseHeader(name, value) | 设置单个响应头 |
setResponseHeaders(headers) | 通过 Headers 对象设置多个响应头 |
setResponseStatus(code) | 设置 HTTP 状态码 |
API 速查
| API | 用途 |
|---|---|
createServerFn() | 创建服务端函数 |
createServerFn({ method: 'POST' }) | 指定 HTTP 方法 |
.inputValidator() | 添加输入验证 |
.handler() | 定义服务端逻辑 |
useServerFn() | 在组件中使用服务端函数 |
分享: