对于每天多次部署的前端团队而言,构建时间从来不是「快一点」还是「慢一点」的问题,而是一笔直接计入每一次迭代的成本。Railway 最近的工程实践验证了这一点:他们将整个前端从 Next.js 迁移到 Vite + TanStack Router 构建体系后,构建时间从超过 10 分钟缩短到 2 分钟以内,200 多条路由在两个 PR 中完成迁移,实现了零停机部署。

问题的根源:Next.js 在 Railway 场景下的失效

Railway 选择 Next.js 起步并无问题 —— 它帮助 railway.com 从零成长为月活数百万的生产级应用。但随着产品演进,框架与业务之间的契合度逐渐崩塌。

构建时间失控是最直接的信号。前端构建慢慢攀升至 10 分钟以上,其中仅 Next.js 本身就消耗了 6 分钟,有一半卡在「finalizing page optimization」阶段。对于一个每天多次发版的团队来说,这意味着每一次代码提交都要额外等待 10 分钟 —— 这不是微不足道的困扰,而是一种昂贵的迭代税。

更深层的问题在于业务特性与框架设计的不匹配。Railway 的产品本质上是高度交互式的客户端应用:仪表盘是富状态界面,Canvas 是实时协作场景,WebSocket 连接无处不在。Next.js 的服务端优先原语(server-first primitives)对于这类产品几乎没有用武之地。团队实际上是在 Next.js 之上自行构建了一套抽象,来填补 Pages Router 在布局和路由处理上的不足。

这直接导致了另一个恶性循环:团队仍在使用 Pages Router,但共享布局只能通过 hack 方式实现 —— 每个布局模式都是强行附加的变通方案,而非框架的一等公民。虽然 App Router 理论上可以解决部分布局问题,但它本质上仍然是服务端渲染导向的,而 Railway 的产品明确是客户端驱动的。如果采用 App Router,意味着要围绕一套自己根本不需要的范式重建整个架构。

技术选型:为什么是 Vite + TanStack Router

Railway 最终选择了 Vite 配合 TanStack Start(现称 TanStack Router)作为新的技术栈,核心驱动力有三:与团队实际构建方式一致极致的后端开发体验、以及明确的客户端模型

在路由层面,TanStack Router 提供了开箱即用的类型安全路由 —— 路由参数和搜索参数自动推断,整个路由树的自动补全,路由直接从文件系统生成。这消除了大量手动类型声明和运行时错误。在布局层面,路径无关的布局路由(pathless layout routes)将之前所有的 hack 方式替换为可组合、可预测的原生机制。

开发循环的提速是关键收益。Vite 提供了即时 HMR 和几乎为零的启动时间,代码修改与结果预览之间的反馈循环几乎透明化。对于需要快速迭代的产品团队来说,这种「忘记工具存在」的开发体验与性能指标同等重要。

服务端渲染仍然被保留,但只在真正需要的地方使用 —— 营销页面、更新日志、招聘页面采用纯服务端渲染,其他所有场景均为纯客户端渲染。团队明确表示不会在不需要服务端渲染的屏幕上强制使用 SSR。

迁移策略:两个 PR 的精确执行

迁移一个服务于数百万用户、涉及 200 多条路由的生产前端,通常意味着数月的并行运行和渐进式切换。但 Railway 在严格的交付时间线下,选择了一种极具纪律性的双 PR 方案。

第一个 PR 替换了所有 Next.js 相关依赖。这包括 next/imagenext/headnext/router 等,每一个都被替换为原生浏览器 API 或框架无关的替代方案。这个 PR 本身不改变框架本身,只是解除对 Next.js 的依赖,为下一步的框架切换做好清洁准备。

第二个 PR 完成了框架的彻底替换。团队首先将页面文件中所有非路由相关的逻辑提取为独立的 React 组件,然后从原始页面树生成所有路由。这种「先拆分再生成」的方式确保了迁移过程的可追溯性和可回滚性。

在底层配置层面,团队用 Nitro 替换了 next.config.js,将 500 多条重定向、安全头和缓存规则统一管理。同时用浏览器原生 API 替换了 Next.js 曾经提供的 Node.js polyfill(如 Buffer、url.parse 等),代码质量也随之提升。

两个 PR 均在周日凌晨合并,团队立即在 Discord 进行实时「狗粮」测试,当天修复了一系列问题,实现了零停机迁移

权衡与取舍

任何架构迁移都不是单方面的收益。Railway 明确列出了迁移过程中放弃的能力:

内置图像优化被替换为 Fastly 边缘图像优化服务,虽然失去了 Next.js 的开箱即用能力,但边缘优化提供了更好的全球分发性能。部分生态系统工具(如 next-seo、next-sitemap)被自研的轻量级替代方案取代,逻辑简单到无需额外依赖。框架成熟度是更现实的风险 ——TanStack Start 作为较新的方案,边缘情况必然存在,团队表示他们接受这一点,因为方向正确且维护者响应积极,Railway 同时赞助了 Vite 和 TanStack 项目。

可落地的构建优化参数

基于 Railway 的实践,以下参数和监控点可作为类似迁移的参考基准:

构建时间目标应设定在 2 分钟以内(CI 环境),开发服务器启动时间目标为 3 秒以内,HMR 延迟目标为 毫秒级。对于静态资源,应采用内容哈希命名的不可变 bundle,确保单模块变更仅触发对应 chunk 的缓存失效。边缘缓存策略应区分静态页面(CDN 完全缓存)和动态页面(按需 ISR),避免前端服务器承担不必要的计算负载。

监控指标应覆盖每次 PR 或 commit 的构建耗时、开发服务器启动耗时、首次内容绘制(FCP)时间以及边缘 CDN 的缓存命中率。这些数据能够帮助团队持续评估架构决策的实际效果。


资料来源:本文核心事实与数据来自 Railway 官方博客《Moving Railway's Frontend Off Next.js》(2026 年 4 月 3 日)。