Railway 的整個生產前端已不再運行於 Next.js。儀表板、Canvas、railway.com,所有這些現在都運行於 Vite + TanStack Router,並且我們在兩次合併請求 (PR) 中實現了零停機遷移。
Next.js 曾幫助 railway.com 從零開始成長為一個每月服務數百萬用戶的生產應用程式。它是一個優秀的框架,但它已不再適合我們的產品。
前端建置時間已悄悄超過 10 分鐘。其中有 6 分鐘僅 Next.js 就佔據了,一半的時間卡在「優化頁面最終化」階段。對於一個每天發布數次的團隊來說,這種建置時間不是小小的困擾,而是每一次迭代都要付出的昂貴稅金。
Railway 的應用程式絕大多數是客戶端渲染。儀表板是一個豐富、狀態化的介面。Canvas 是即時的。WebSocket 無處不在。Next.js 中以伺服器為優先的原生功能並非我們所使用的,我們最終在 Pages Router 上建置了自己的抽象層,以支援框架本身無法以我們所需方式處理的佈局和路由問題。
我們仍然在使用 Pages Router,這使得共用佈局變得棘手。每一個佈局模式都像是硬加上去的解決方案,而不是框架本身提供的第一級功能。App Router 雖然能解決其中一些問題,但它嚴重依賴以伺服器為優先的模式,而我們的產品是刻意以客戶端為主導的。採用它意味著需要圍繞一個我們並不需要的範式進行重建。
我們想要一個能匹配我們實際建置方式的堆疊:明確、以客戶端為優先、且能快速迭代。而且,我們確實很喜歡使用它。
對於產品團隊來說,我們希望有一些便利的功能,能幫助我們不必思考如何實施前端,並發現以下幾點確實說服了我們。
假期期間,我們中的幾個人嘗試了 TanStack Start,反應是出奇的一致。我們喜歡用它來建置,對於像 Railway 儀表板這樣的產品,這點和任何效能指標一樣重要。
一旦我們做出決定,我就開始動手了。在合併前的壓縮提交 (pre-squash) 中,我可能提交了數百次。
遷移一個服務數百萬用戶、橫跨 200 多個路由的生產前端,通常需要數月的平行運行和逐步切換。我們有時間壓力,所以我把它分成了兩個合併請求 (PR)。
PR 1 替換了所有 Next.js 特有的部分:next/image、next/head、next/router。每一個都被替換為原生的瀏覽器 API 或框架無關的替代方案。這個 PR 本身沒有改變框架的任何內容,它只是移除了所有對它的依賴,以便 PR 2 可以進行乾淨的替換。
PR 2 替換了框架。遷移了 200 多個路由。我們系統性地將頁面檔案中所有與路由無關的部分提取到單獨的 React 組件中,然後從原始頁面樹狀結構生成所有路由。
接著,我們添加了 Nitro 作為伺服器層,並用 Nitro 設定替換了 next.config.js,將重新導向 (500+)、安全標頭和快取規則整合到一個地方。我們還用瀏覽器原生 API 替換了 Next.js 提供 Polyfill 的 Node.js API(如 Buffer、url.parse 等),這也順帶讓我們的程式碼更乾淨。
於週日清晨合併。團隊立即在 Discord 的線上會議室進行了內部測試 (dogfooding),當天就陸續修復了問題。沒有停機。
當然,我們獲得了一個更快、更明確的堆疊,但也有取捨。
我們運行生產前端的方式與我們的用戶運行他們的方式相同:每個 PR 都有預覽部署、健康檢查、零停機推出。當我們替換了整個建置系統和框架時,我們沒有觸碰基礎設施。我們更改了程式碼,推送了它,剩下的由 Railway 來處理。
現在,Fastly 直接從邊緣 (edge) 提供我們大部分流量。行銷頁面被快取,動態頁面在需要時使用 ISR (Incremental Static Regeneration),結果是我們的伺服器大部分時間處於閒置狀態。Vite 的資產模型讓這尤其有效。每個模組都有自己的內容雜湊區塊,因此發布對帳單的變更只會使該區塊失效。回訪用戶下載的是千位元組,而不是百萬位元組。
這就是我們認為前端應該部署的方式:建置快速,資產不可變且易於快取,底層基礎設施處理推出、預覽和路由,而無需您費心。您的前端框架應該針對迭代速度進行優化,而您的基礎設施應該讓這些迭代的發布變得無感。這就是我們為自己和 Railway 上的所有人正在建置的體驗。
前端的迭代速度比以往任何時候都更重要。
過去需要 10 分鐘以上的建置現在不到兩分鐘就能完成。開發伺服器即時啟動。路由變更會在邊界進行類型檢查。佈局可以無需變通地組合。
從編寫程式碼到將其呈現給用戶之間的差距是瓶頸,而我們在這裡所做的一切,包括框架替換、邊緣快取、資產模型,都是為了縮小這個差距。Vite + TanStack 為我們設定了一個發布前端變更幾乎是即時的世界,這就是我們正在努力實現的世界。
立即合併,準備好時發布:為您的團隊開啟一個功能,然後是 10% 的用戶,然後是所有人。功能標記 (Feature flags) 現在已內建於每個 Railway 專案中,您的代理程式可以從 CLI、SDK 和 MCP 運行推出。無需第三方服務。
Railway 於 2026 年 7 月 2 日 UTC 時間約 07:44 至 12:01 之間,在我們的一個美國東部可用區域發生了重大中斷。