超越 Next.js:TanStack Start 与全栈 React 开发的未来
Source: Dev.to
背景
在使用 Next.js 构建了 4–5 年后,我看到这个框架从一个简单、可预测的工具演变成了更为复杂的东西。Next.js 对于合适的使用场景仍然非常强大,但不断变化的思维模型让许多开发者感到疲惫。
Next.js 推出时,的确是一次革命。在此之前,构建一个可投入生产的 React 应用意味着要协调 webpack、Babel、路由库以及无数其他工具——每个工具都有自己的配置怪癖。Next.js 说:“给你一个完整的方案。它处理路由、渲染、优化,一切都搞定。直接使用就行。”
Pages Router 简单且可预测:基于文件的路由直观易懂,API 路由自然顺手,整体思维模型一致。
使用 Next.js 的挑战
从 Next.js 13 开始,情况变得不太稳定。React Server Components(RSC)与 App Router 同时出现,框架频繁改变其基础假设。
- 服务器优先默认 – “use client”、 “use server” 与 “use cache” 指令颠覆了范式,导致频繁的水合问题。
- 缓存模型的变化 – Next.js 14 默认缓存所有内容;Next.js 15(配合 Turbopack)则相反,需要显式选择缓存。
// Next.js 15 – 使用 'use cache' 指令显式缓存
'use cache'
export async function getData() {
const data = await fetch('/api/data')
return data
}
Next.js 15 将 Turbopack 设为默认(或至少大力推广)的构建工具,摆脱了 Webpack。基于 Rust 的打包器承诺 10 倍性能提升,但实际数据呈现出喜忧参半的结果——热刷新表现优秀,却偶尔出现导入破损、资源消耗高、冷启动慢等问题。
Vercel 发布了一篇官方指南《Next.js App Router 十大常见错误》,足以说明问题的严重性。
何时使用 Next.js
- 内容丰富的网站 – 博客、文档、电子商务产品目录。
- SEO 关键页面 – 需要服务器渲染的营销首页。
对于大约 70 % 需要交互且带有一定服务器端需求的应用来说,不断添加 “use client” 边界并管理服务器/客户端复杂性的摩擦已经难以忽视。
介绍 TanStack Start
TanStack Start 是一个基于稳定、经过实战检验的工具构建的全栈框架:
- TanStack Router – 类型安全的路由。
- Vite – 行业标准的构建工具。
截至 2025 年 11 月,它已脱离 beta(v1),处于活跃开发阶段,社区采纳度不断提升。与 Next.js 不同,TanStack Start 在基础理念上保持了一致性。
关键区别
| 方面 | Next.js | TanStack Start |
|---|---|---|
| 默认渲染 | 服务器优先(React Server Components) | 客户端优先;SSR 需在路由上显式开启 |
| 路由 | 基于文件,类型安全有限 | TanStack Router,完整 TypeScript 推断 |
| 构建工具 | Turbopack(默认)或 Webpack | Vite |
| 缓存 | 随版本变化的默认设置 | 通过 ssr 属性在每条路由上显式配置 |
| 思维模型 | 服务器中心,需大量 “use client” 标记 | 客户端中心,SSR 作为可选功能 |
每条路由的 SSR 配置
// TanStack Start – 每条路由的 SSR 配置
// 纯客户端渲染(类似传统 SPA)
export const Route = createFileRoute('/dashboard')({
ssr: false,
component: DashboardComponent,
})
// 对 SEO 关键页面进行完整 SSR
export const Route = createFileRoute('/products')({
ssr: true,
loader: async () => fetchProducts(),
component: ProductsComponent,
})
// 仅 SSR 数据:服务器端获取数据,客户端渲染
export const Route = createFileRoute('/admin')({
ssr: 'data-only',
loader: async () => fetchAdminData(),
component: AdminComponent,
})
哲学
- 客户端优先的思维模型 – 首先考虑客户端体验来编写代码。
- SSR 按路由显式开启 – 与 Next.js 需要“退出”不同,TanStack Start 让你在需要时主动开启 SSR。
- 默认同构代码 – 路由 loader 在服务器(首次加载)和客户端(导航)都会运行。
类型安全与路由
TanStack Start 会生成 routeTree.gen.ts 文件,包含每条路由的完整类型信息——这是 Next.js 所不具备的功能。
// routes/products.$id.tsx
export const Route = createFileRoute('/products/$id')({
loader: async ({ params }) => {
// params.id 会自动得到完整的类型推断
return getProduct(params.id)
},
component: ProductComponent,
})
function ProductComponent() {
const product = Route.useLoaderData() // 完全类型安全!
return {product.name}
}
导航在编译时即安全:
navigate({
to: '/products/$id',
params: { id: productId }, // TypeScript 会校验此处
})
结论
Next.js 仍然是内容丰富、SEO 为核心站点的优秀选择,但其服务器优先的默认行为以及不断变化的思维模型会给高度交互的应用带来摩擦。TanStack Start 提供了客户端优先的方式,支持按路由显式的 SSR、强大的类型安全路由,以及基于 TanStack Router 与 Vite 等成熟工具的稳定生态。对于需要在客户端交互与选择性服务器渲染之间取得平衡的项目,TanStack Start 是一个极具吸引力的替代方案。