对比 | TanStack Start vs Next.js vs React Router
正在选型一个全栈 React 框架?这份对比聚焦于能区分 TanStack Start 与 Next.js、React Router(v7 Framework Mode)的全栈框架特性。
重要:想找路由特性?
TanStack Start 建立在 TanStack Router 之上,它提供了业界领先的类型安全路由能力。想看路由特性的全面对比(嵌套路由、搜索参数、类型安全、加载器等),请阅读:
📖 TanStack Router 对比 React Router / Next.js →
那份对比详细覆盖了所有路由特性。本页则专注于全栈框架能力,比如 SSR、服务器函数、中间件、部署等。
我们力求提供准确、公平的对比,但请注意,这张表可能无法涵盖每个框架的全部细节或最新更新。建议查阅各框架的官方文档并亲自上手试一试,才能针对你的具体场景做出最明智的选择。
如果你发现任何出入,或有改进建议,欢迎通过本页底部的「Edit this page on GitHub」链接直接贡献,或在 TanStack Router GitHub 仓库中提 issue。
特性/能力图例:
- ✅ 一等支持:内置、开箱即用,无需额外配置或代码
- 🟡 部分支持(标注处按 1-5 评分)
- 🟠 通过附加包/社区包支持
- 🔶 可以实现,但需要自定义代码/实现/类型断言
- 🛑 官方不支持
| TanStack Start | Next.js (官网) | React Router (官网) | |
|---|---|---|---|
| GitHub 仓库 / Stars | |||
| 打包体积 | ❓ | ❓ | |
| -- | -- | -- | -- |
| 路由特性 (查看完整对比) | ✅ 基于 TanStack Router | ✅ 基于文件的路由(App Router) | ✅ 基于文件的嵌套路由 |
| -- | -- | -- | -- |
| 全栈特性 | -- | -- | -- |
| SSR | ✅ | ✅ | ✅ |
| 流式 SSR(Streaming SSR) | ✅ | ✅ | ✅ |
| 选择性 SSR(按路由) | ✅ | 🔶 | 🔶 |
| SPA 模式 | ✅ | 🔶(通过 "use client") | ✅ |
| 内置客户端 SWR 缓存 | ✅(通过 TanStack Router) | 🔶(仅 fetch 缓存) | 🛑 |
| 数据获取库集成 | ✅(官方 TanStack Query、Apollo 等) | 🔶(手动集成) | 🔶(手动集成) |
| 静态预渲染(SSG) | ✅ | ✅ | ✅ |
| 增量静态再生成(ISR) | ✅(通过 Cache-Control 头) | ✅(专有实现) | ✅(通过 Cache-Control 头) |
| React 服务器组件 | 🟡(实验性) | ✅ | 🟡(实验性) |
| 服务器函数 | ✅(基于 RPC) | ✅(Server Actions) | ✅(Actions) |
| 服务器函数客户端中间件 | ✅ | 🛑 | 🛑 |
| 服务器函数服务端中间件 | ✅ | 🛑 | ✅ |
| 请求中间件(所有路由) | ✅ | ✅ | ✅ |
| 服务器函数输入校验 | ✅ | 🔶(手动) | 🔶(手动) |
| API 路由 / 服务器路由 / 资源路由 | ✅ | ✅ | ✅ |
<Form> API | 🛑 | 🟠(通过 React 19 useActionState) | ✅ |
| -- | -- | -- | -- |
| 开发者体验 | -- | -- | -- |
| 开发者工具(Devtools) | ✅ | 🛑 | 🟠(第三方) |
| CLI 工具 | ✅ | ✅ | ✅ |
| 开发服务器启动速度 | ✅(快) | 🛑(慢) | ✅(快) |
| HMR 速度 | ✅(快,Vite 或 Rsbuild) | 🛑(慢,Webpack/Turbopack) | ✅(快,Vite) |
| 开发时导航速度 | ✅ | 🟡 | ✅ |
| 开发时资源占用(CPU/RAM) | ✅(轻量) | 🛑(重) | ✅(轻量) |
| TypeScript 支持 | ✅ | ✅ | ✅ |
| 类型优先架构 | ✅ | 🛑 | 🛑 |
| -- | -- | -- | -- |
| 部署与托管 | -- | -- | -- |
| 部署灵活性 | ✅(Vite 和 Rsbuild 构建) | 🟡(为 Vercel 优化,其他平台可行) | ✅(多种适配器) |
| 边缘运行时支持 | ✅ | ✅ | ✅ |
| Serverless 支持 | ✅ | ✅ | ✅ |
| Node.js 支持 | ✅ | ✅ | ✅ |
| Docker 支持 | ✅ | ✅ | ✅ |
| 静态导出 | ✅ | ✅ | ✅ |
| 官方 Cloudflare 支持 | ✅ | 🟡 | ✅ |
| 官方 Netlify 支持 | ✅ | 🟡 | ✅ |
| 官方 Vercel 支持 | ✅(通过 Nitro) | ✅ | ✅ |
再次提醒
想对比路由特性(类型安全、搜索参数、加载器、导航等)的细节,请看 TanStack Router 对比。本页只聚焦于全栈框架能力。
关键理念差异
TanStack Start
理念:在顶尖类型安全之上,给开发者最大的自由度。
- 路由优先:基于 TanStack Router(详见完整路由对比)
- 部署无关:基于 Vite 和 Rsbuild 集成,部署时不绑定任何厂商
- 可组合的中间件:中间件系统同时作用于请求层面和单个服务器函数层面(客户端与服务端皆可)
- 选择性 SSR:按路由细粒度控制 SSR 行为(完整 SSR、仅数据、或仅客户端)
- 开发者掌控:显式、可组合的模式,而非基于约定的魔法
- 类型安全优先:服务器函数、加载器和路由的端到端编译期安全
Next.js
理念:生产就绪、默认配置最佳,与 Vercel 配合最好。
- RSC 优先:深度集成 React 服务器组件,作为首要范式
- 为 Vercel 优化:在 Vercel 基础设施上获得最佳性能和开发体验
- 约定优于配置:基于文件系统路由约定的强约定结构
- 自动优化:许多性能优化自动完成
- 生产级:经过大规模生产环境的严酷考验
React Router(v7 Framework Mode)
理念:立足 Web 平台基础,渐进增强。
- Web 标准:拥抱 Web 平台原语(fetch、FormData、Headers)
- 渐进增强:默认无 JavaScript 也能工作
- 嵌套路由:一等支持嵌套路由与数据加载
- 基于 Action:通过 action 的表单提交遵循 Web 标准
- 框架演进:Remix 的后继者,基于 Vite 架构
什么时候该选哪个框架
选 TanStack Start,如果你:
- 想要路由方面绝对顶级的类型安全(见路由对比)
- 需要不受厂商绑定的部署灵活性(兼容 Vite 和 Rsbuild 构建)
- 偏好可组合、显式的模式,而不是约定
- 想对 SSR 行为做细粒度控制(按路由选择性 SSR)
- 需要既作用于请求层面、又作用于服务器函数层面的可组合中间件
- 正在构建一个能从 TanStack Router 高级特性中获益的复杂应用
- 已经在使用 TanStack Query 或其他 TanStack 库
选 Next.js,如果你:
- 想现在就使用 React 服务器组件,并拥有完整的生态支持
- 要部署到 Vercel,或想要为 Vercel 优化的体验
- 为了更快起步,偏好约定优于配置
- 想要自动化的图片优化和字体加载
选 React Router,如果你:
- 把渐进增强放在首位
- 希望应用在没有 JavaScript 的情况下也能工作
- 偏好遵循 Web 约定的基于 action 的变更(mutation)
特性深入
内置客户端缓存
TanStack Start 通过 TanStack Router 内置了强大的 SWR(stale-while-revalidate,过期再验证)缓存:
- 开箱即用的性能——加载器数据自动缓存并重新验证
- 细粒度控制——按路由配置
staleTime、gcTime和重新验证策略 - 结构共享——高效更新,只重新渲染变化的部分
- 官方集成——开箱即用地支持 TanStack Query、Apollo 等数据获取库
- 更高性能——为即时导航和后台更新优化了用户体验
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => fetchPost(params.postId),
staleTime: 10_000, // Consider fresh for 10 seconds
gcTime: 5 * 60_000, // Keep in memory for 5 minutes
})在更高级的场景下,TanStack Start 可以与 TanStack Query 无缝集成:
import { queryOptions } from '@tanstack/react-query'
const postQueryOptions = (postId: string) =>
queryOptions({
queryKey: ['post', postId],
queryFn: () => fetchPost(postId),
})
export const Route = createFileRoute('/posts/$postId')({
loader: ({ context, params }) =>
context.queryClient.ensureQueryData(postQueryOptions(params.postId)),
})
function Post() {
const { postId } = Route.useParams()
const { data } = useQuery(postQueryOptions(postId))
// Automatically uses cached data from loader
}Next.js 有基础的 fetch 缓存,但缺少细粒度控制,而且与 React Query 这类库的集成需要手动完成。
React Router 没有内置客户端缓存——你需要手动集成一个缓存方案。
服务器函数 vs Server Actions
TanStack Start 服务器函数:
export const getTodos = createServerFn({ method: 'GET' })
.validator(zodValidator(z.object({ userId: z.string() })))
.middleware([authMiddleware])
.handler(async ({ data, context }) => {
// Fully typed data and context
return db.todos.findMany({ where: { userId: data.userId } })
})
// Call from anywhere with full type safety
const todos = await getTodos({ data: { userId: '123' } })Next.js Server Actions:
'use server'
export async function getTodos(userId: string) {
// Runs on server, called from client
return db.todos.findMany({ where: { userId } })
}
// Call from client component
const todos = await getTodos('123')关键区别:
- Start 的服务器函数同时支持客户端和服务端中间件
- Start 内置输入校验
- Start 的方式对客户端/服务端边界更明确
- Start 的服务器函数同时支持 GET 和 POST 方法(通过
method选项配置,默认 GET),而 Next.js Server Actions 只支持 POST - Next.js Server Actions 与表单集成得更无缝
中间件架构
TanStack Start 有两种中间件:
- 请求中间件:作用于所有请求(SSR、API 路由、服务器函数)
- 服务器函数中间件:专门作用于服务器函数,支持客户端和服务端两端的执行
这种可组合性可以这样用:
const authMiddleware = createMiddleware({ type: 'function' })
.client(async ({ next }) => {
// Run auth checks on client
return next({
headers: { Authorization: `Bearer ${getToken()}` },
})
})
.server(async ({ next }) => {
// Validate auth on server
return next({ context: { user: await getUser() } })
})Next.js 有一个在 Node.js 运行时上运行的 proxy.ts 文件。与已弃用的 middleware.ts(在边缘运行时运行)不同,proxy.ts 可以完全访问数据库等服务端资源。
部署灵活性
TanStack Start 充分利用现代构建工具生态:
- 可部署到 Cloudflare Workers、Netlify、Vercel、Railway、Fly.io、AWS 等
- 使用 Nitro 获得通用部署支持
- 没有厂商专属特性或锁定
- 同一份代码在任何地方都能运行
Next.js 为 Vercel 优化:
- 许多特性在 Vercel 上表现最好或只能在 Vercel 上使用(ISR、图片优化、中间件)
- 自托管需要更多配置
- 部署到其他平台可能有限制
React 服务器组件(RSC)
当前状态:
- Next.js:完整生产支持,生态庞大
- TanStack Start:实验性支持
- React Router:实验性支持
TanStack Start 的 RSC 实现采用「客户端主导组合」的方式:服务器组件被当作客户端可以获取、缓存和组合的数据。详见 Server Components 指南。
性能考量
生产性能
三个框架都能达到出色的生产性能和满分的 Lighthouse 分数。差异在于优化策略:
- TanStack Start:优化过的打包构建,SWR 缓存降低服务器负载,运行时轻量
- Next.js:自动代码分割、图片优化、内置性能特性
- React Router:基于 Web 标准的缓存与优化
开发性能
这里才是各框架差异巨大的地方:
TanStack Start 与 React Router:
- ⚡ 开发服务器秒启——Vite 和 Rsbuild 启动飞快
- ⚡ 闪电般快的 HMR——改动即时生效,无需刷新页面
- ⚡ 快速的开发导航——开发时全速路由
- ⚡ 低资源占用——CPU 和内存消耗极低
- ⚡ 高开发吞吐——高效处理大量并发请求
Next.js:
- 🐌 开发服务器启动慢——可能需要很多秒才能启动,项目越大越明显
- 🐌 HMR 慢——即使有 Turbopack,热重载也明显迟钝
- 🐌 开发导航被限速——开发时导航被人为减慢
- 🐌 资源占用高——开发期间消耗大量 CPU 和内存
为什么这很重要:
开发性能直接影响到开发者的生产力。更快的反馈循环意味着:
- 每小时更多次迭代
- 更好的心流状态和专注度
- 更低的硬件要求
- 开发过程中更少的挫败感
- 更快的开发构建 CI/CD 流水线
虽然 Next.js 的生产性能很出色,但开发体验可能明显更慢,尤其是在较大的代码库或配置较低的机器上。
社区与生态
- Next.js:社区最大,第三方集成最多,学习资源最丰富
- React Router:最古老、使用最广泛的 React 库之一,社区强大,文档出色
- TanStack Start:社区在成长,属于 TanStack 生态,Discord 支持出色
成熟度
- Next.js:生产就绪,数千家公司使用,经受过大规模验证
- React Router:生产就绪,支撑着数百万应用,v7 Framework Mode 是 Remix 的演进
- TanStack Start:Release Candidate 阶段,功能完整,正快速向 v1 稳定