Next.js 和 TanStack Start 都能 SSR、streaming、server functions/RSC。但它们默认认为“好框架”应该做的事不同。
| 问题 | Next.js 倾向 | TanStack 倾向 |
|---|---|---|
| 框架该替你决定多少? | 多。平台集成、文件约定、默认缓存、默认 server-first。 | 少。给原语,让你显式组合。 |
| 组件默认交互性 | App Router 中 Server Components 默认,交互要 "use client"。 | 传统交互式 React 默认 SSR + hydrate;RSC 是可选/实验能力。 |
| 缓存心智模型 | 多层隐式缓存:fetch/data/full route/router/RSC stream。 | 数据就是数据:Router SWR、Query、HTTP/CDN、数据库缓存各自选择。 |
| 部署 | Vercel 最顺,其他平台常有适配成本。 | Vite/Rsbuild + runtime adapter,部署目标是显式选择。 |
Next.js 的强项是“把主路径铺好”。如果你的项目刚好落在主路径上,非常舒服。TanStack 的强项是“边界清楚”:URL 状态、loader 依赖、server function 输入、middleware context 都能被你看见并验证。
// app/products/page.tsx
export default async function Page({ searchParams }) {
const page = Number(searchParams.page ?? 1)
const products = await fetchProducts({ page })
return <Products products={products} />
}简单直接,但 searchParams 的类型和校验通常靠你自己补。
const searchSchema = z.object({ page: z.number().catch(1) })
export const Route = createFileRoute('/products')({
validateSearch: searchSchema,
loaderDeps: ({ search }) => ({ page: search.page }),
loader: ({ deps }) => fetchProducts(deps),
component: ProductsPage,
})多几个显式边界,但它们形成类型和缓存依赖。
TanStack 的核心卖点最接近哪一句?