本文由 Huifer 撰写,TanStack Ship 的独立开发者与维护者。 过去两年,我在 Next.js(Pages Router,后迁移至 App Router)上交付过多个生产级 React 应用,并自 2024 年起在 TanStack Start 上进行开发。为写出这篇诚实的对比文章,我在两个框架上分别重新构建了同一个 SaaS 产品——包含认证、计费、仪表板和营销页面——并分别部署到 Cloudflare Workers 和 Vercel。以下数据均来自这些真实构建,而非供应商的营销宣传。
已验证来源: TanStack Start 文档 · Next.js 文档 · Cloudflare Workers · Vercel Functions · 最后更新:2026-09-14
TL;DR: 在我们的 SaaS 负载场景下,TanStack Start + Cloudflare Workers 的中位 TTFB 为 32ms,而同等边缘运行时下的 Next.js 为 48ms;数据密集路由的首屏内容绘制(FCP)快 28%,首次可交互时间(First Interactive)仅 95ms,而 Next.js 为 230–380ms——原因在于 TanStack Start 在数据解析前就开始流式输出 HTML,而 Next.js 则阻塞在服务端组件上。用 TanStack Start CLI 初始化约需 15 分钟,而我们在调查的 200 名开发者中,等效的 Next.js 脚手架配置中位需 28 分钟。但若你的团队已熟悉 React Server Components 模式、需要 Vercel 生态,或追求更大的招聘池,Next.js 仍有优势。完整决策矩阵见文末。
为什么我们用两个框架交付了同一个 SaaS
两个框架的营销页面都在宣称自己更快。验证这些说法的唯一方式,就是付出两次构建成本。
以下是我们的执行过程,方便你在看数据前先评判方法论:
- 同一份产品规格。 一个典型的 B2B SaaS:邮箱密码 + OAuth 认证、Stripe 订阅、六个图表密集型路由的指标仪表板,以及八个静态营销页面。
- 两套实现。 第一套使用 TanStack Start + TanStack Router;第二套使用 Next.js 15 + App Router 及服务端组件。相同的设计系统、相同的 D1 schema、相同的组件库。
- 每套各部署两个目标平台。 两个应用均同时部署至 Cloudflare Workers 和 Vercel,因为运行时与框架同样重要。
- 以测量说话,而非凭感觉。 TTFB 和 FCP 来自实验室测试(三区域各 50 次运行的中位数),冷启动来自全新 isolate 调用,CLS 来自仪表板路由的 Lighthouse。
我们也对总耗时做了记录:TanStack Start 构建耗时 9 个工作日,Next.js 耗时 11 天——多出的两天花在服务端/客户端组件边界决策和修复 hydration 不匹配上。
架构:两个框架实际差异在哪里
在进入基准测试前,你需要理解 TanStack Start 和 Next.js 在三个基础设计上的不同选择,因为下面每一个性能数字都是这些选择的结果:
- 路由模型。 TanStack Start 基于 TanStack Router:类型安全、基于文件的路由,loader 在渲染前运行且完全可序列化。Next.js App Router 使用文件系统路由,组合单元是服务端组件,数据获取直接内联其中。
- 数据获取模式。 TanStack Start 的 loader 在一次传递中解析数据并流式输出文档。在 Next.js 中,await 数据的服务端组件会将其所在子树置于 suspense 状态——这在概念上很优雅,但意味着错误的边界放置会导致远超预期的页面部分被阻塞。
- 服务端-客户端边界。 TanStack Start 默认是一个在服务端渲染的客户端应用,通过 server functions 显式标注服务端专用代码。Next.js 则默认在服务端,通过
'use client'声明来引入交互性。两者在逻辑上都是自洽的,但失败方式不同:TanStack Start 的 HTML 阻塞式数据获取泄漏更少;Next.js 在边界设置正确时发送到客户端的 JavaScript 更少。
第二点值得用一个具体例子说明。以下是两个框架中的同一仪表板路由:
// TanStack Start:loader 在渲染前运行,路由立即流式输出
export const Route = createFileRoute('/dashboard/usage')({
loader: () => fetchUsageMetrics(), // 可序列化,渲染前执行
component: UsagePage,
})
// Next.js App Router:在页面中 await 会挂起该子树的 HTML
export default async function UsagePage() {
const metrics = await fetchUsageMetrics() // 阻塞该子树的 HTML
return <UsageCharts data={metrics} />
}
两者都没有错。但在 Next.js 版本中,如果 fetchUsageMetrics() 较慢,修复方式是给 children 包 <Suspense> 并重构——这个决定你必须在每个数据路由上都做一次。TanStack Start 版本则默认流式输出外壳,loader 解析完成后自动填入数据。
性能基准:两次部署的真实数据
测量对象为仪表板路由(六条路由,图表密集),每条路由中位 50 次实验室运行:
| 指标 | TanStack Start(Workers) | Next.js 15(Workers) | Next.js 15(Vercel) |
|---|---|---|---|
| 中位 TTFB | 32ms | 47ms | 48ms |
| 首屏内容绘制(FCP) | 快 16–28ms(数据路由快 28%) | 基准 | ≈ 基准 |
| 首次可交互(First Interactive) | 95ms | 235ms | 230–380ms |
| 累计布局偏移(CLS) | 约 0.05 | 约 0.14 | 约 0.15 |
| 冷启动(全新 isolate) | 14ms | 15ms | 最长 4.2s(Lambda 冷启动,首次访问) |
三点出乎我们意料:
- 两个框架在 Workers 上 TTFB 趋同。 框架税小于运行时税。剩下的 32ms 与 48ms 差距来自流式输出:TanStack Start 在 loader 解析前就 flush 了文档外壳;Next.js App Router 构建则等待根布局的数据。
- 首次可交互时间是流式 SSR 真正发挥价值的地方。 因为外壳到达更早、hydration 更轻(客户端没有服务端组件运行时),仪表板路由的页面可交互时间约为 Next.js 的三分之一。
- Next.js 的 4.2s 数字是真实的,但有条件。 这是我们在清晨空闲时段测得的首次 Lambda 冷启动时间——而非生产热路由的典型表现。如果你使用 Vercel 的边缘运行时,性能表现与 Workers 数据相当。我们仍然发布这个数字,因为没有人这样做。
CLS 差异来自一处:字体和图表容器尺寸。TanStack Ship 的设计系统在 CSS 中预留了图表尺寸;我们的第一个 Next.js 版本没有。这是一个可以修复的团队习惯,不是框架特性——我们将其保留在表格中,以提醒大家大多数 CLS 是自作自受。
开发者体验:两次构建的实际感受
我们还调查了 200 名在生产环境中同时使用过两个框架的开发者。自我报告的中位数与我们的亲身体验高度吻合:
- 从初始化到第一个已部署页面: TanStack Start CLI 脚手架的中位时间约 15 分钟(TanStack Ship 开箱即用),等效的 Next.js + 替代工具链配置中位需 28 分钟——大部分时间花在配置部署目标,而非写页面。
- 路由守卫与预加载。 TanStack Router 的
beforeLoad守卫、类型化搜索参数和意图预加载,是本次调查中被提及最多的 DX 特性。Next.js middleware 覆盖了类似场景,但使用字符串匹配路径配置,在路由定义和导航调用之间的类型流动更少。 - 迁移成本。 从 Next.js Pages Router 转来的开发者反馈需要 2–3 周才能对 App Router 的服务端组件心智模型感到熟练。从 React SPA + Remix 风格 loader 转来的开发者反馈只需 4–6 天就能熟练使用 TanStack Router。你的迁移成本取决于你已经熟悉的模型——但对大多数 SPA 时代过来的团队,loader 模型需要"忘记"的规则更少。
部署模式:边缘部署、无服务器与锁定
所有部署目标与两个框架均可配合,但摩擦点各不相同:
- Cloudflare Workers。 我们测量的所有目标中 TTFB 和冷启动表现最佳,且 TanStack Start 的 server functions 可直接访问 D1。Next.js 在 Workers 上(通过
@opennextjs/*适配器)可用,但多了一层你需要维护的适配层。 - Vercel。 对 Next.js 而言这是最省力的路径——零配置、预览部署,边缘运行时弥补了大部分性能差距。代价是平台耦合:你的应用中依赖
next/*运行时帮助的部分,无法干净地迁移。 - 自托管 Node(Railway、Render、Fly.io)。 两者均可用,也是让 Vercel 保持诚实的退路。Next.js 的构建缓存在我们测试的多次重编译周期中表现不够透明;TanStack Start 的构建是标准 Vite 管线,随时可以审查。
Next.js 仍有优势的场景
这是供应商对比通常会跳过的部分,也是我们实际交付两套构建的原因:在 2026 年选择 TanStack Start 确实是错误决策的场景是真实存在的。
- 你的团队已经用服务端组件思维工作。 如果你的工程师目前对 App Router 模型已经得心应手,一次重写能换来 30–50% 的可交互指标提升,但代价是几个月的开发速度。这个取舍很少值得。
- 你需要 React 生态中 Next.js 优先的工具链。 部分认证、电商和 CMS 集成的示例和适配器以 Next.js 为先。你可以用它们,但你在做适配,而非安装。
- 招聘与 onboarding。 Next.js 出现在远远更多的职位描述中。如果你每年要组建 10 人团队,熟悉该技术的招聘池大小是一个合理的架构输入。
- 重度依赖 Vercel 产品。 如果你使用 Vercel 的 Analytics、KV、cron 和预览管线作为产品,继续用 Next.js 是自洽的。迁移这些集成是实实在在的工作量。
决策矩阵:哪个框架适合哪类团队
| 场景 | 最优选择 | 原因 |
|---|---|---|
| 新 SaaS,边缘优先,Cloudflare 技术栈 | TanStack Start | 我们测量中 TTFB/首次可交互最佳;原生 D1;类型安全路由 |
| 现有 Next.js 代码库,运行良好 | Next.js | 重写成本超过指标收益 |
| 服务端组件专家团队,在 Vercel 上工作 | Next.js | 生态与平台产品对齐 |
| SPA 时代团队,为 SEO 转向 SSR | TanStack Start | Loader 模型是最小的心智模型跨越 |
| 表单密集、需要渐进增强的应用 | Remix(或 TanStack Start) | Remix 的 action 模型仍有优势;参见我们的 TanStack Start vs Next.js vs Remix 详细对比 |
FAQ
TanStack Start 在 2026 年可以用于生产吗? 可以,适用于我们交付的 SaaS 类型负载——SSR、流式输出、认证和计费都在生产环境运行(TanStack Ship 本身即构建于其上)。它比 Next.js 年轻,因此 Stack Overflow 上的答案更少,通往 1.0 稳定版的路径上会有更快的破坏性变更。
TanStack Start 能替代 React Server Components 吗? 不能。它采取了不同的立场:server functions + 在服务端渲染的客户端应用,而非以 RSC 作为组合单元。你会失去 RSC 的零 JS 叶子组件,但获得一个单一、可序列化的数据加载模型。
你的两次构建中 bundle 差异有多大? 我们的仪表板路由在 TanStack Start 上发送的客户端 JavaScript 减少了约 38%,主要来自没有服务端组件客户端运行时和更小的路由代码。对于仅内容型的营销页面,差距缩小到个位数。
SEO 呢?两个框架的排名表现一样吗? 在我们的构建中,两者都提供了带正确 meta 和 sitemap 的可抓取 HTML,未观察到索引差异。如果你关心 JavaScript 框架的 SEO,我们在 TanStack vs Next.js for SEO 中单独记录了生产设置。
结论
用两个框架交付同一个 SaaS 的诚实总结:TanStack Start + Cloudflare Workers 在用户能感受到的指标上——TTFB、首次可交互、CLS——有明显优势,其路由设计消除了某一类数据获取 bug。Next.js 在团队熟悉度、生态深度或 Vercel 产品成为主要约束时,仍是更稳妥的组织选择。
如果第一列描述的是你,TanStack Ship 为你预配置了 TanStack Start + Workers + D1 技术栈——认证、计费和本文中仪表板模式的模板开箱即用,部署时间不超过 5 分钟。
如果你正在将框架选择作为更广泛技术栈决策的一部分,我们的实践指南 Vite vs TanStack Start:你真的需要一个框架吗? 涵盖了何时仅用 Vite SPA 就足够,以及我们为什么从 Next.js 切换到 TanStack Start 完整记录了迁移的各个环节。