WordPress 轉移至 Next.js:金融 SaaS 節省 $420K ARR
您的合規人員在晚上 9:47 發送電子郵件:頁面加載時間達到 4.2 秒,這是監管風險。您的首席財務官在一小時後轉發 $420K 年度 CMS 續約,只寫了一個詞:「為什麼?」兩條線索都指向同一個 WordPress 整體系統——行銷網站、客戶入口網站和文件中心由 19 個高級插件和許可成本超過兩名工程師的堆棧組成。這個 Series C 金融 SaaS 背後需要一個無頭 Next.js 遷移,該遷移消除停機時間,因為在金融科技領域,每一秒的離線都會引發監管人員的審查和企業客戶的抱怨電話。他們還需要成本結構在下一次董事會會議之前有所改善。我們在 90 天內完成了遷移,將基礎設施支出減少了 73%,同時將頁面速度提高了三倍——但最難的部分不是代碼。
這是我們如何實現的完整故事。
目錄
- 起點:在壓力下的 WordPress 整體系統
- 為什麼無頭 Next.js 是正確選擇
- 遷移架構
- 零停機策略:並行運行
- 性能結果:快 3 倍及以上
- $420K 許可證節省明細
- 技術深入探討:關鍵實現細節
- 困難中學到的教訓
- 時間表和團隊結構
- 常見問題

起點:在壓力下的 WordPress 整體系統
讓我描繪一下情況。這家公司——我們稱之為 FinEdge(保密協議,您理解)——在三個不同的網站屬性中大約有 12,000 頁內容:
- 行銷網站 ——產品頁面、登陸頁面、包含 2,400+ 篇文章的博客
- 客戶入口網站 ——帳戶儀表板、入門工作流程、文件管理
- 文件中心 ——API 文件、合規指南、整合教程
所有三個都在 WP Engine 企業級託管的單個 WordPress 多站點安裝上運行。插件情況是……令人驚訝。他們運行著 47 個活躍插件,包括 WPGraphQL、Advanced Custom Fields Pro、Yoast SEO Premium、WP Rocket、Gravity Forms,以及他們之前的代理商構建的自訂插件,用於處理內容變更的 SOC 2 合規日誌記錄。
真正的痛點:
- 行動裝置上的頁面加載時間平均 4.2 秒(Google CrUX 數據)
- 68% 的頁面核心網頁指標失敗 ——LCP 在 5.1 秒中位數時很糟糕
- 許可證年度支出 $420K,包括 WP Engine 企業級託管、高級插件、WAF、CDN 和獨立的預發佈環境
- 內容編輯在高峰時段等待 8-12 秒 WordPress 管理員做出回應
- 安全補丁 需要每兩週專門的 DevOps 時間——金融服務監管人員不會妥協
- 沒有預覽部署 ——內容團隊必須推送到預發佈並等待 4 分鐘的快取失效
他們的工程副總裁在發現電話中告訴我們:「我們在網站基礎設施上花費的費用比兩名高級工程師還多。而且它還是很慢。」
為什麼無頭 Next.js 是正確選擇
我們在架構階段評估了幾個選項。以下是需要考慮的事項:
| 選項 | 優點 | 缺點 | 估計年度費用 |
|---|---|---|---|
| WordPress(最佳化) | 團隊熟悉,無需遷移 | 仍然很慢,許可證未變 | $420K |
| Webflow Enterprise | 視覺編輯,快速部署 | 入口網站/應用需求有限,供應商鎖定 | $180K |
| Next.js + Sanity | 超快速,靈活,實時預覽 | 遷移工作,團隊學習曲線 | $38K |
| Next.js + Contentful | 強大的企業功能,良好的開發體驗 | 按用戶定價擴展不佳 | $95K |
| Astro + Storyblok | 靜態內容很好,輕量級 | 動態入口網站需求成熟度較低 | $42K |
我們選擇了 Next.js 14(App Router)加上 Sanity 作為無頭 CMS。原因如下:
- FinEdge 的入口網站具有需要伺服器端呈現的動態、經過身份驗證的路由。Next.js 使用 React Server Components 原生處理此問題。
- Sanity 的實時協作和 GROQ 查詢語言為內容編輯提供了比 WordPress 好得多的體驗。
- 定價模型(Sanity 的 Growth 計畫 $99/月 + Vercel Pro)意味著基礎設施成本從 $420K 下降到大約 $38K 年度。
- 他們的工程團隊已經了解 React。升級到 Next.js 的時間以天計,而不是月。
我們確實認真考慮了 Astro 用於文件中心,因為它大多是靜態內容,但保持一個框架的操作簡單性勝出。如果文件網站是一個獨立項目,Astro 會是首選。
遷移架構
以下是我們設計的高級架構:
┌─────────────────┐ ┌──────────────────┐
│ Sanity CMS │────▶│ Next.js on │
│ (Content) │ │ Vercel (Edge) │
└─────────────────┘ └──────────────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Cloudflare │
│ │ (DNS + WAF) │
│ └──────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Media Pipeline │ │ End Users │
│ (Cloudinary) │ └──────────────────┘
└─────────────────┘
關鍵組件:
內容層
- Sanity 作為行銷內容、部落格文章和文件的主要 CMS
- 對應於其現有 WordPress 內容類型的自訂 Sanity 架構
- 用於豐富內容的 Portable Text(替換 WordPress 的 Gutenberg 區塊)
應用層
- Next.js 14 與 App Router,部署在 Vercel 的 Pro 計畫上
- 行銷網站和文件的 React Server Components
- 客戶端組件僅在真正需要互動的地方(表單、儀表板、互動圖表)
- 入口網站路由的中間件,集成其現有 Auth0 設定
基礎設施層
- Vercel 用於託管和邊緣函數
- Cloudflare 用於 DNS 管理和其他 WAF 規則(金融服務合規要求)
- Cloudinary 用於影像最佳化和轉換——替換了 3 個 WordPress 影像插件

零停機策略:並行運行
這是讓我夜不能寐的部分。FinEdge 無法承受甚至幾分鐘的停機時間。他們的客戶入口網站處理金融交易,任何中斷都會觸發對監管機構的強制事件報告。
以下是我們的做法:
第 1 階段:內容同步(第 1-3 週)
我們構建了一個自訂 WordPress 轉 Sanity 同步管道,在遷移期間持續運行:
// 我們的 WP 轉 Sanity 同步工作者的簡化版本
import { createClient } from '@sanity/client'
import WPGraphQL from './wp-graphql-client'
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID,
dataset: 'production',
token: process.env.SANITY_WRITE_TOKEN,
apiVersion: '2024-10-01',
useCdn: false,
})
async function syncPosts(since: string) {
const posts = await WPGraphQL.getModifiedPosts(since)
const transaction = sanity.transaction()
for (const post of posts) {
const sanityDoc = transformWPToSanity(post)
transaction.createOrReplace(sanityDoc)
}
await transaction.commit()
console.log(`Synced ${posts.length} posts`)
}
// 每 5 分鐘通過 cron 運行
這意味著內容編輯可以在整個遷移期間繼續在 WordPress 中工作。他們所做的每項變更都會在 5 分鐘內自動同步到 Sanity。
第 2 階段:並行部署(第 4-8 週)
我們在子域上部署了 Next.js 網站(next.finedge.com),並同時運行兩個網站。我們的品質保證流程比較了每一頁:
- 跨 200+ 個關鍵頁面的視覺回歸測試(使用 Playwright)
- SEO 奇偶性檢查(meta 標籤、結構化資料、規範 URL、網站地圖)
- 每個頁面範本的性能基準
- 無障礙審計(WCAG 2.1 AA ——金融服務必需)
第 3 階段:切換(第 9 週)
實際的切換是平凡的——這正是您想要的。我們使用 Cloudflare 的負載平衡來逐漸轉移流量:
- 第 0 小時: 5% 流量到 Next.js,95% 到 WordPress
- 第 2 小時: 25% / 75%(監視錯誤率、Core Web Vitals)
- 第 6 小時: 50% / 50%
- 第 12 小時: 90% / 10%
- 第 24 小時: 100% Next.js,WordPress 為唯讀模式
- 第 2 週: WordPress 停用
零個錯誤。零停機時間。監視儀表板令人厭煩地顯示綠色。
性能結果:快 3 倍及以上
以下是使用 Google CrUX 數據和 Vercel Analytics 在遷移後 30 天測量的實際數字:
| 指標 | WordPress(之前) | Next.js(之後) | 改進 |
|---|---|---|---|
| LCP(p75) | 5.1 秒 | 1.2 秒 | 快 4.25 倍 |
| FID / INP(p75) | 280ms | 68ms | 快 4.1 倍 |
| CLS(p75) | 0.18 | 0.02 | 改進 9 倍 |
| TTFB(p75) | 1.8 秒 | 0.12 秒 | 快 15 倍 |
| Lighthouse 性能 | 34 | 96 | +62 點 |
| 通過 CWV 的頁面 | 32% | 98% | +66% |
| 互動時間 | 6.8 秒 | 1.4 秒 | 快 4.9 倍 |
「快 3 倍」的標題實際上低估了它。在大多數指標上,我們看到了 4-5 倍的改進。TTFB 是明星——得益於 Vercel 的邊緣網絡和 ISR(增量靜態再生),從 1.8 秒降到 120 毫秒。
有機流量在遷移後的前 90 天內增加了 31%。他們的 SEO 團隊主要將這歸因於 Core Web Vitals 改進和 Googlebot 爬蟲速率更快。
$420K 許可證節省明細
讓我們談論金錢。以下是 $420K 具體花在何處,以及 Next.js 如何替換它:
| 項目 | WordPress 年度費用 | Next.js 年度費用 | 節省 |
|---|---|---|---|
| WP Engine Enterprise 託管 | $150,000 | — | $150,000 |
| Vercel Pro(團隊計畫) | — | $2,400 | — |
| 高級插件許可證(47 個插件) | $28,000 | — | $28,000 |
| Sanity Growth 計畫 | — | $1,188 | — |
| Cloudinary Pro | — | $2,388 | — |
| 企業級 WAF(Sucuri) | $36,000 | — | $36,000 |
| Cloudflare Pro | — | $2,400 | — |
| 自訂 WordPress 維護合約 | $96,000 | — | $96,000 |
| CDN(獨立於 WP Engine) | $24,000 | — | $24,000 |
| 預發佈環境託管 | $18,000 | — | $18,000 |
| WordPress 安全審計(季度) | $48,000 | — | $48,000 |
| DevOps 團隊時間(部分 FTE) | $120,000 | $30,000 | $90,000 |
| 合計 | $520,000 | $38,376 | $481,624 |
實際節省最終接近 $482K,而不是 $420K。原始發現階段的 $420K 估計是保守的——我們初始沒有考慮 DevOps 時間的減少或季度安全審計的消除(Vercel 和 Cloudflare 處理這些審計涵蓋的大部分內容)。
ROI 數學很直接。我們在 10 週的合作期間為 FinEdge 進行的 遷移項目 成本大約為 $185K 的代理費用。該投資在不到 5 個月內為自己付費。
技術深入探討:關鍵實現細節
使用 ISR 處理 2,400 篇部落格文章
我們沒有在構建時靜態生成所有 2,400 篇部落格文章。那會使部署極其緩慢。相反,我們使用 ISR 和按需重新驗證:
// app/blog/[slug]/page.tsx
import { sanityFetch } from '@/lib/sanity'
import { postQuery } from '@/lib/queries'
export const revalidate = 3600 // 作為後備每小時重新驗證一次
export async function generateStaticParams() {
// 僅預先生成按流量排名前 100 的文章
const topPosts = await sanityFetch({
query: `*[_type == "post"] | order(pageViews desc) [0...100] { "slug": slug.current }`
})
return topPosts.map((post) => ({ slug: post.slug }))
}
export default async function BlogPost({ params }) {
const post = await sanityFetch({
query: postQuery,
params: { slug: params.slug },
tags: [`post:${params.slug}`]
})
// ... 呈現文章
}
當內容編輯在 Sanity 中發佈或更新時,webhook 點擊我們的重新驗證端點:
// app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache'
import { NextRequest } from 'next/server'
export async function POST(req: NextRequest) {
const body = await req.json()
const secret = req.headers.get('x-sanity-webhook-secret')
if (secret !== process.env.SANITY_WEBHOOK_SECRET) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
// 重新驗證特定內容
if (body._type === 'post') {
revalidateTag(`post:${body.slug.current}`)
revalidateTag('posts-list')
}
return Response.json({ revalidated: true })
}
內容更新現在在不到 3 秒內出現在實時網站上。與 WordPress + WP Rocket 的 4 分鐘快取失效相比。
客戶入口網站的身份驗證
入口網站路由需要伺服器端身份驗證。我們將 Next.js 中間件與現有 Auth0 設定結合使用:
// middleware.ts
import { NextResponse } from 'next/server'
import { getSession } from '@auth0/nextjs-auth0/edge'
export async function middleware(req) {
if (req.nextUrl.pathname.startsWith('/portal')) {
const session = await getSession(req, NextResponse.next())
if (!session?.user) {
return NextResponse.redirect(new URL('/api/auth/login', req.url))
}
}
return NextResponse.next()
}
export const config = {
matcher: ['/portal/:path*']
}
這在邊緣運行,因此未經身份驗證的請求在到達應用程式伺服器之前就會被重定向。快速且安全。
301 重定向映射
在遷移期間,我們有大約 340 個 URL 更改了結構。金融服務網站絕對不能有損壞的連結——來自監管備案、合作夥伴網站和歷史內容的每個入站連結都需要正確解析。
我們在 next.config.js 中構建了重定向映射,並補充了來自 Sanity 的動態重定向查找,用於編輯管理的重定向:
// next.config.js(部分)
module.exports = {
async redirects() {
return [
// 已知 URL 變更的靜態重定向
...require('./redirects.json').map(r => ({
source: r.from,
destination: r.to,
permanent: true,
})),
]
},
}
啟動後六個月,Google Search Console 顯示遷移時零個 404 錯誤。每個重定向都有效。
困難中學到的教訓
1. WordPress Gutenberg 區塊轉換令人困擾
我們低估了將 Gutenberg 區塊轉換為 Sanity 的 Portable Text 所需的工作量。FinEdge 使用了 23 種不同的區塊類型,包括他們之前的代理商構建的自訂區塊。為內容轉換預算比您認為的至少 20% 更多的時間。
2. 內容編輯培訓不是可選的
Sanity 的 Studio 很直觀,但它不是 WordPress。我們進行了三場 90 分鐘的培訓課程,並創建了一個帶有引導工作流程的自訂 Sanity Studio。內容團隊在兩週內從懷疑轉變為熱情,但該培訓投資是關鍵的。
3. 金融服務合規增加複雜性
每次部署都需要審計軌跡。每個內容變更都需要用時間戳和用戶歸屬進行記錄。我們構建了一個自訂 Sanity 插件,將所有文件突變記錄到他們現有 PostgreSQL 資料庫中的僅附加審計表。這額外花了一週,不在原始範圍內。
4. 不要忘記表單
Gravity Forms 在 WordPress 網站上處理 14 種不同的表單類型。我們用 React Hook Form + Zod 驗證前端和伺服器操作後端替換了它們,提交內容發送到他們現有的 HubSpot CRM。僅此遷移就花了一整週。
時間表和團隊結構
總項目持續時間:10 週
| 週 | 焦點 | 團隊 |
|---|---|---|
| 1 | 架構、Sanity 架構設計、內容審計 | 2 名開發者、1 名架構師 |
| 2-3 | 內容同步管道、Sanity Studio 自訂 | 2 名開發者、1 名內容策略師 |
| 4-5 | 行銷網站構建(Next.js) | 3 名開發者 |
| 6-7 | 入口網站遷移、身份驗證、表單 | 3 名開發者 |
| 8 | 文件中心、SEO 審計、重定向映射 | 2 名開發者、1 名 SEO 專家 |
| 9 | 品質保證、視覺回歸、性能測試 | 2 名開發者、1 名品質保證 |
| 10 | 逐步流量切換、監視、WordPress 停用 | 2 名開發者、1 名 DevOps |
峰值團隊規模為 4 人。大多數項目以 2-3 名開發者運行。這不是一個 15 人、6 個月的合作——這是一個專注、經驗豐富的團隊執行周密計劃的遷移。
如果您考慮為組織進行類似的遷移,我們已經記錄了我們的 無頭 CMS 開發方法,我們的 定價結構 是透明的。我們也很樂意通過電話討論您的具體情況——在此聯繫。
常見問題
WordPress 轉 Next.js 遷移通常需要多長時間? 對於這種複雜度的網站(12,000 頁、客戶入口網站、文件中心),10 週對經驗豐富的團隊來說是現實的。更簡單的行銷網站,有 100-500 頁,可以在 4-6 週內遷移。最大的變量是內容複雜性——您運行多少自訂文章類型、區塊類型和依賴插件的功能。
可以在沒有任何停機時間的情況下將 WordPress 遷移到 Next.js 嗎? 是的,但這需要規劃。關鍵是運行兩個系統並行,使用內容同步管道,然後使用 DNS 級流量轉移逐步將用戶遷移到新網站。我們已經為多個客戶成功做到了這一點。關鍵要求是在過渡期間您的內容在兩個系統之間保持同步。
WordPress 轉無頭 CMS 遷移成本多少? 它的範圍很大取決於範圍。簡單的行銷網站遷移可能花費 $30K-$60K。像 FinEdge 的企業遷移——有客戶入口網站、合規要求和 12,000 頁——為 $185K。ROI 計算的重要性超過絕對成本。FinEdge 的投資在不到 5 個月內通過許可證節省為自己付費。
Next.js 比 WordPress 確實更快嗎? 在幾乎所有情況下,是的——顯著更快。WordPress 在每個請求上生成 HTML(除非有大量快取),即使使用 WP Rocket 等快取插件,您也受到 PHP 回應時間和 WordPress 生態系統權重的限制。Next.js 使用 ISR 或靜態生成從邊緣提供預構建的頁面。我們通常看到 Core Web Vitals 改進 3-5 倍。
應該在 Next.js 中使用什麼無頭 CMS? 這取決於您的團隊和要求。Sanity 擅長自訂內容建模和實時協作。Contentful 對於想要更結構化、主觀方法的企業團隊很強,但按座位定價變得昂貴。Storyblok 很好,如果視覺編輯是優先級的話。對於更簡單的網站,甚至 Git repo 中的 Markdown 文件都能起作用。我們逐個項目評估這個——沒有通用答案。
從 WordPress 遷移到 Next.js 時會失去 SEO 嗎? 如果操作正確,就不會。三件重要的事:全面 301 重定向映射,以便沒有現有 URL 返回 404、保留所有 meta 標籤和結構化資料,以及在切換後立即向 Google Search Console 提交更新的網站地圖。FinEdge 在 90 天內看到有機流量增加 31%,主要由 Core Web Vitals 改進驅動。
遷移後 WordPress 插件會發生什麼? 每個插件的功能都需要被複製或替換。有些很直接——SEO 插件被替換為 Next.js 組件中的元資料、快取插件變得不必要,表單插件被替換為 React 表單庫。其他的,如自訂合規日誌插件,需要自訂替換代碼。這是為什麼在發現期間進行徹底的插件審計至關重要。
遷移到無頭後內容編輯仍能使用視覺編輯器嗎? 是的。Sanity Studio 提供可自訂的編輯介面,具有實時預覽。它與 WordPress 的區塊編輯器不同,但大多數內容團隊在初始學習曲線後更喜歡它。Sanity 的 Presentation 工具現在提供真正的視覺編輯,具有實時預覽的點擊編輯功能。我們還在 Vercel 上設置了預覽部署,以便編輯可以在發佈前準確看到其內容的外觀。