已超出 WordPress 適用範圍?Next.js + Supabase 遷移地圖
你打開 WordPress 儀表板,更新圖標再次呈現紅色。你點擊。三個外掛衝突。聯絡表單停止工作。你的客戶在晚上 11 點發電子郵件,因為網站感覺緩慢,你已經知道:到交互需要六秒,如果有人在行動設備上則需要七秒。安全通知在第二天早上到達——CVE-2022-something——外掛作者已經在兩年前消失了。你修補了你能修補的,推遲了你無法修補的,並向自己承諾這是最後一次。但下一個更新週期已經兩週後了,你正盯著同樣的權衡:穩定性或功能,永遠無法同時擁有兩者。有一個更好的技術棧在等著——它不會讓你進行選擇。
這就是情況——WordPress 為超過 40% 的網際網路提供動力,這是有充分理由的。它易於使用,具有龐大的生態系統,並讓許多企業快速上線。但在讓你入門的工具和隨著你成長的工具之間有差異。如果你正在閱讀本文,你可能已經達到了那堵牆。讓我引導你了解從 WordPress 到無頭式 Next.js + Supabase 架構的真實遷移過程——不是行銷版本,而是實際的工程行動手冊。
目錄
- 確實超出 WordPress 適用範圍的跡象
- WordPress 稅收:外掛地獄實際成本
- 為什麼 Next.js + Supabase 是合理的技術棧
- 遷移手冊:分階段
- 數據遷移:從 WordPress 導出你的內容
- 使用 Next.js 構建新前端
- 將 Supabase 設置為後端
- 處理身份驗證和用戶數據
- SEO 保留:不要失去你建立的東西
- 性能基準:前後對比
- 成本比較:WordPress vs 無頭式技術棧
- 常見問題

確實超出 WordPress 適用範圍的跡象
不是每個人都需要離開 WordPress。我想提前坦白。如果你經營個人博客或本地企業的宣傳網站,具有良好主題和少數外掛的 WordPress 可能仍然是正確選擇。但有明確的信號表明你已經超出了它的適用範圍:
外掛衝突每月都在破壞東西
你更新 WooCommerce,你的頁面構建器會破壞。你更新你的頁面構建器,你的 SEO 外掛會發出警告。你更新 PHP 到 8.2 因為你的主機要求這樣,三個外掛完全停止工作。這不是一個 bug——這是架構。WordPress 外掛都共享相同的全局作用域、相同的鉤子、相同的數據庫。每個外掛都是與其他每個外掛衝突的潛在因素。
我已經審計了執行 30、40、甚至 60+ 個活躍外掛的 WordPress 網站。此時,你不是在維護網站。你在維護堆疊遊戲。
性能已成為全職工作
你的 PageSpeed 分數在 30 秒。你已安裝了緩存外掛、圖像優化外掛、縮小外掛和 CDN 外掛——所有這些都是為了解決其他 25 個外掛造成的性能問題。諷刺很厚重。
WordPress 在每個請求時動態生成頁面(除非緩存)。每個外掛都可以注入自己的 CSS 和 JavaScript 文件。具有流行外掛的典型 WordPress 頁面加載 15-30 個單獨的呈現阻止資源。Google 的核心網頁活力數據顯示 WordPress 網站在所有三個 CWV 指標上的通過率為 33%,而使用現代 JavaScript 框架構建的網站為 52%。
安全漏洞讓你夜不能寐
WPScan 的漏洞數據庫已追蹤數千個 WordPress 漏洞——絕大多數在外掛和主題中。如果你執行處理用戶數據、付款或任何敏感信息的網站,每個外掛都是攻擊面。Patchstack 報告 97% 的 WordPress 安全漏洞來自外掛。
你基本上是在信任數十個獨立開發人員——其中許多人將外掛作為副項目維護——來維護你的安全姿態。
你的開發團隊討厭在上面工作
這個被低估了。優秀的開發人員不再想在 WordPress 上工作。PHP 樣板意大利麵條與 ACF 字段的工作流相比,與基於現代組件的開發相比是痛苦的。如果你試圖吸引和保留工程人才,你的技術棧很重要。
WordPress 稅收:外掛地獄實際成本
讓我為此提供一些數字。對於中型 WordPress 網站(比如電子商務網站或具有博客、用戶帳戶和自定義功能的 SaaS 行銷網站),「WordPress 稅收」在年度基礎上通常看起來像這樣:
| 成本類別 | 年度估計 |
|---|---|
| 高級外掛許可證(15-20 個外掛) | $1,500 - $4,000 |
| 託管 WordPress 主機(WP Engine、Kinsta) | $1,200 - $6,000 |
| 安全監控 + 清理(Sucuri、Wordfence) | $300 - $500 |
| 性能優化時間(開發人員工時) | $3,000 - $8,000 |
| 外掛衝突調試(開發人員工時) | $2,000 - $6,000 |
| 更新破壞東西的緊急修復 | $1,000 - $4,000 |
| 總年度 WordPress 稅收 | $9,000 - $28,500 |
這是在你構建單個新功能之前。這是保持燈亮著的成本。
為什麼 Next.js + Supabase 是合理的技術棧
有十幾種方式去無頭式。你可以使用 Gatsby(雖然自 Netlify 收購它以來基本上處於維護模式)。你可以使用 Remix、Astro 或 SvelteKit。對於後端,你可以使用 Firebase、PlanetScale 或自定義 API。
但對於從 WordPress 在 2026 年遷移的團隊,Next.js + Supabase 達到了難以克服的甜蜜點。這是為什麼。
Next.js:全能前端
Next.js 15(自 2024 年 10 月以來穩定)默認提供伺服器組件,這意味著你獲得靜態網站的性能,具有動態網站的靈活性。你可以在構建時靜態生成博客文章,伺服器呈現動態頁面,客戶端呈現交互組件——所有內容都在同一應用中。
對於來自 WordPress 的團隊,關鍵優勢是:
- 內置圖像優化——取代 2-3 個 WordPress 外掛
- 自動代碼分割——每個頁面只加載它需要的 JS
- 邊界中間件——在 CDN 級別處理重定向、身份驗證和 A/B 測試
- 增量靜態再生成 (ISR)——無需完整部署即可重建各個頁面
- 使用 React 伺服器組件的應用路由器——大幅減少客戶端 JavaScript
我們在 Social Animal 構建了許多 Next.js 項目(查看我們的 Next.js 開發功能),與 WordPress 相比性能差異一直很戲劇性。
Supabase:後端 WordPress 希望擁有的
Supabase 是基於 PostgreSQL 構建的開源 Firebase 替代品。它提供:
- 完整的 Postgres 數據庫,具有從架構自動生成的 REST 和 GraphQL API
- 內置身份驗證(電子郵件、OAuth、魔法鏈接、SSO)
- 用於細粒度訪問控制的行級安全策略
- 通過 WebSockets 的實時訂閱
- 用於無服務器後端邏輯的邊界函數
- 用於文件上傳和 CDN 交付的存儲
特別是對於 WordPress 遷移,Supabase 很出色,因為 WordPress 使用 MySQL,你的數據模型映射到 PostgreSQL 的效果出人意料地好。自定義文章類型變為表。文章元變為 JSONB 列。用戶數據幾乎 1:1 映射。
Supabase 的免費層包括 500MB 數據庫、1GB 存儲和 5 萬個每月活躍用戶的身份驗證。他們的專業計畫每月 $25,涵蓋大多數生產網站。將此與你單獨在託管 WordPress 主機上支付的 $30-$100/月相比。

遷移手冊:分階段
這是我在數十次 WordPress 遷移中完善的方法。它不是一個週末項目——根據網站複雜性預算 4-12 週——但如果你遵循各個階段,它是可預測且低風險的。
階段 1:審計和架構(第 1 週)
在你寫一行代碼之前:
- 匯出完整外掛列表,使用
wp plugin list --status=active(WP-CLI) - 將每個外掛映射到新堆棧中的替代品
- 匯出你的完整 URL 結構,包括所有文章、頁面、分類和自定義文章類型
- 記錄所有表單、集成和第三方連接
- 識別自定義功能,在你主題的
functions.php中
外掛映射練習很重要。常見的替代品看起來像這樣:
| WordPress 外掛 | 無頭式替代品 |
|---|---|
| Yoast SEO | Next.js 內置元數據 API + generateMetadata() |
| WP Super Cache / W3 Total Cache | 無需(默認為靜態) |
| Wordfence / Sucuri | Supabase RLS + Vercel 的內置 DDoS 防護 |
| Contact Form 7 / Gravity Forms | React Hook Form + Supabase 邊界函數 |
| WooCommerce | Saleor、Medusa.js 或 Shopify Storefront API |
| ACF / 自定義字段 | Supabase 表,具有類型化架構 |
| WP Migrate DB | 一次性 Supabase 遷移腳本 |
| Smush / ShortPixel | Next.js Image 組件(內置) |
| Elementor / WPBakery | React 組件(你不會想念他們) |
階段 2:設置新堆棧(第 2 週)
# 建立你的 Next.js 項目
npx create-next-app@latest my-site --typescript --tailwind --app --src-dir
# 安裝 Supabase
npm install @supabase/supabase-js @supabase/ssr
# 設置環境變數
cp .env.example .env.local
你的 .env.local:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
立即部署到 Vercel。是的,在你構建任何有意義的東西之前。從第一天有活動預覽 URL 改變了你的工作方式——利益相關者可以看到進度,你會及早發現部署問題。
數據遷移:從 WordPress 導出你的內容
這是大多數遷移指南變得模糊的地方。讓我具體說明。
步驟 1:匯出 WordPress 數據
不要使用內置的 WordPress XML 匯出。它不完整且結構不良。而是使用 WP-CLI 和直接數據庫查詢:
# 將文章匯出為 JSON
wp post list --post_type=post --format=json --fields=ID,post_title,post_content,post_excerpt,post_date,post_status,post_name > posts.json
# 匯出頁面
wp post list --post_type=page --format=json --fields=ID,post_title,post_content,post_excerpt,post_date,post_status,post_name > pages.json
# 匯出自定義文章類型
wp post list --post_type=your_cpt --format=json > cpt.json
# 匯出文章元(ACF 字段等)
wp eval 'global $wpdb; $results = $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE meta_key NOT LIKE \"_%\""); echo json_encode($results);' > postmeta.json
步驟 2:轉換並加載到 Supabase
編寫遷移腳本。我傾向於為此使用 TypeScript:
import { createClient } from '@supabase/supabase-js'
import posts from './exports/posts.json'
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
async function migratePosts() {
for (const post of posts) {
const { error } = await supabase.from('posts').insert({
wp_id: post.ID,
title: post.post_title,
slug: post.post_name,
content: convertWpContentToMdx(post.post_content),
excerpt: post.post_excerpt,
published_at: post.post_date,
status: post.post_status === 'publish' ? 'published' : 'draft',
})
if (error) console.error(`Failed to migrate post ${post.ID}:`, error)
}
}
function convertWpContentToMdx(html: string): string {
// 使用 turndown 或 rehype 將 WordPress HTML 轉換為 MDX
// 處理短碼、嵌入和 Gutenberg 塊
// 這是 80% 遷移複雜性所在
}
convertWpContentToMdx 函數是你花費最多時間的地方。WordPress 內容是 HTML、短碼、Gutenberg 塊註釋和嵌入式 oEmbed URL 的混合。像 turndown 這樣的庫處理基本的 HTML 到 Markdown 轉換,但你需要為短碼和塊提供自定義規則。
步驟 3:遷移媒體
import { createClient } from '@supabase/supabase-js'
import fetch from 'node-fetch'
async function migrateMedia(mediaItems: any[]) {
for (const item of mediaItems) {
const response = await fetch(item.source_url)
const buffer = await response.buffer()
const { error } = await supabase.storage
.from('media')
.upload(`uploads/${item.slug}.${item.mime_type.split('/')[1]}`, buffer, {
contentType: item.mime_type,
})
if (error) console.error(`Failed to upload ${item.slug}:`, error)
}
}
使用 Next.js 構建新前端
將數據放入 Supabase 後,構建前端是有趣的部分。這是使用 Next.js 應用路由器的典型博客文章頁面:
// src/app/blog/[slug]/page.tsx
import { createClient } from '@/lib/supabase/server'
import { notFound } from 'next/navigation'
import { MDXRemote } from 'next-mdx-remote/rsc'
export async function generateMetadata({ params }: { params: { slug: string } }) {
const supabase = createClient()
const { data: post } = await supabase
.from('posts')
.select('title, excerpt, og_image')
.eq('slug', params.slug)
.single()
if (!post) return {}
return {
title: post.title,
description: post.excerpt,
openGraph: { images: [post.og_image] },
}
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
const supabase = createClient()
const { data: post } = await supabase
.from('posts')
.select('*')
.eq('slug', params.slug)
.eq('status', 'published')
.single()
if (!post) notFound()
return (
<article className="prose lg:prose-xl mx-auto">
<h1>{post.title}</h1>
<time dateTime={post.published_at}>
{new Date(post.published_at).toLocaleDateString()}
</time>
<MDXRemote source={post.content} />
</article>
)
}
注意沒有緩存外掛、沒有性能外掛、沒有 SEO 外掛。元數據 API 處理 SEO。伺服器組件處理性能。CDN 處理緩存。一切都是內置的。
將 Supabase 設置為後端
你的 Supabase 架構應該圍繞你的實際數據需求設計,而不是 WordPress 的通用 wp_posts / wp_postmeta 結構。這是一個更清晰的架構:
-- 文章表
create table posts (
id uuid default gen_random_uuid() primary key,
title text not null,
slug text unique not null,
content text,
excerpt text,
featured_image text,
status text default 'draft' check (status in ('draft', 'published', 'archived')),
author_id uuid references auth.users(id),
published_at timestamptz,
created_at timestamptz default now(),
updated_at timestamptz default now(),
metadata jsonb default '{}'
);
-- 分類
create table categories (
id uuid default gen_random_uuid() primary key,
name text not null,
slug text unique not null,
description text
);
-- 行級安全
alter table posts enable row level security;
create policy "Published posts are viewable by everyone"
on posts for select
using (status = 'published');
create policy "Authors can manage their own posts"
on posts for all
using (auth.uid() = author_id);
metadata jsonb 列是你的逃生艙。任何不值得擁有自己列的自定義字段都可以存在於此。它被索引、可查詢和無限靈活——喜歡 ACF 字段但沒有外掛。
處理身份驗證和用戶數據
如果你的 WordPress 網站有用戶帳戶,Supabase 身份驗證乾淨地處理遷移。你無法遷移密碼哈希(WordPress 使用 phpass,Supabase 使用 bcrypt),但你可以:
- 將用戶電子郵件和個人資料導入 Supabase
- 在首次登錄時為所有用戶觸發「重置密碼」流程
- 或使用魔法鏈接身份驗證,因此無需密碼
Supabase 支持電子郵件/密碼、Google、GitHub、Apple 和開箱即用的數十個其他 OAuth 提供商。無需外掛。
SEO 保留:不要失去你建立的東西
這是不可協商的。拙劣的遷移可以在一夜之間摧毀多年的 SEO 資產。這是檢查清單:
將每個舊 URL 映射到其新 URL。 WordPress 默認使用
/2024/01/post-title/。你的新網站可能使用/blog/post-title。每個舊 URL 都需要一個 301 重定向。在 Next.js 中實施重定向:
// next.config.js
module.exports = {
async redirects() {
return [
// 基於日期的 WordPress URL 以清除 slug
{
source: '/:year(\\d{4})/:month(\\d{2})/:slug',
destination: '/blog/:slug',
permanent: true,
},
// 分類頁面
{
source: '/category/:slug',
destination: '/blog/category/:slug',
permanent: true,
},
]
},
}
- 保留所有元標題、描述和結構化數據。 在遷移前從 Yoast 匯出它們。
- 在啟動後立即向 Google Search Console 提交新的站點地圖。
- 在子域 (old.yoursite.com) 上繼續執行舊網站 30 天作為後備。
性能基準:前後對比
這是 Social Animal 遷移項目中的實際數字(這些是遷移項目中的平均值):
| 指標 | WordPress(之前) | Next.js + Supabase(之後) | 改進 |
|---|---|---|---|
| Lighthouse 性能分數 | 38 | 94 | +147% |
| 最大內容繪製 (LCP) | 4.2 秒 | 0.9 秒 | -79% |
| 首次輸入延遲 (FID) | 180 毫秒 | 12 毫秒 | -93% |
| 累積佈局偏移 (CLS) | 0.25 | 0.02 | -92% |
| 首字節時間 (TTFB) | 1.8 秒 | 0.15 秒 | -92% |
| 總頁面權重 | 3.2MB | 420KB | -87% |
| HTTP 請求 | 47 | 8 | -83% |
這些不是精心挑選的。它們是一致的。當你消除 30+ 個外掛,每個都注入自己的 CSS 和 JS,並在全球 CDN 上用靜態/伺服器呈現的 React 組件替換動態 PHP 呈現時,結果是可預測的。
如果你對這些結果對你的項目的影響感到好奇,我們的定價頁面 詳細說明了無頭式遷移項目通常成本多少。
成本比較:WordPress vs 無頭式技術棧
| WordPress(年度) | Next.js + Supabase(年度) | |
|---|---|---|
| 主機 | $1,200 - $6,000(WP Engine/Kinsta) | $0 - $240(Vercel Pro) |
| 數據庫/後端 | 託管主機中包含 | $0 - $300(Supabase Pro) |
| 外掛許可證 | $1,500 - $4,000 | $0 |
| 安全工具 | $300 - $500 | $0(內置) |
| CDN | $0 - $600 | $0(Vercel 中包含) |
| 維護開發工時 | $6,000 - $18,000 | $1,000 - $4,000 |
| 總計 | $9,000 - $29,100 | $1,000 - $4,540 |
無頭式技術棧的年度運營成本便宜 70-85%。遷移本身有前期成本,很明顯——通常對於專業構建,複雜性取決於 $15,000-$60,000(有關詳細信息,請參閱我們的 無頭式 CMS 開發服務)。但它在 6-18 個月內通過降低運營成本償付,在你考慮更好的性能和 SEO 的收入影響之前。
常見問題
遷移後我是否需要學習 React/Next.js 來管理我的內容? 否。大多數團隊將 Next.js 與無頭式 CMS(如 Sanity、Contentful 或 WordPress 本身使用純無頭式 CMS)配對(通過其 REST API)。內容編輯器從不接觸代碼。他們得到一個乾淨的編輯界面,前端通過 API 拉取內容。如果你想保留你的團隊已經知道的 WordPress 編輯器,你絕對可以——只需移除 WordPress 前端並將其用作內容後端。
典型的 WordPress 到 Next.js 遷移需要多長時間? 對於以內容為重點的網站,包括博客和標準頁面:4-6 週。對於具有電子商務、用戶帳戶、自定義文章類型和複雜功能的網站:8-14 週。最大的變數是內容複雜性——具有大量短代碼依賴內容或深度自定義 Gutenberg 塊的網站需要更長時間來乾淨地遷移。
在遷移期間我會失去我的 Google 排名嗎? 不,如果你正確處理重定向。301 重定向保留約 90-99% 的鏈接資產。我們通常在遷移後的前 1-2 週看到排名小幅下降(Google 需要重新爬取),然後由於更好的核心網頁活力分數而排名改進。關鍵是映射每個單一 URL,並且在啟動前不啟動直到你的重定向地圖完整。
Supabase 對於高流量網站是否已做好生產準備? 是的。Supabase 在 AWS 基礎設施上執行,並已被處理數百萬請求的公司在生產中使用。他們的數據庫只是 PostgreSQL——可以說是現存最經過戰鬥測試的數據庫。Supabase 服務超過 100 萬個數據庫,每天處理數十億個 API 請求。要獲得額外的規模,他們的專業($25/月)和團隊($599/月)計畫包括專用資源和優先支援。
我能將 WooCommerce 遷移到此技術棧嗎? 你可以,但電子商務增加了重大複雜性。大多數從 WooCommerce 遷移的團隊要麼去 Shopify(使用 Storefront API 與 Next.js 前端),要麼去開源解決方案,如 Medusa.js 或 Saleor。Supabase 可以處理產品目錄和訂單管理,但你需要自己構建結帳、付款處理、庫存管理和稅收計算。對於大多數業務,使用專用電子商務後端並將其連接到 Next.js 更有意義。
WordPress 多網站——此技術棧能替換它嗎? 絕對地。Next.js 對多租戶架構有出色的支持,使用中間件和動態路由。Supabase 的行級安全使按租戶分區數據變得簡單。我們已經將 50+ 個網站的 WordPress 多網站網絡遷移到單個 Next.js 應用,具有特定於租戶的路由,運營簡化非常巨大。
我仍然需要 CMS,還是我可以直接使用 Supabase? Supabase 為開發人員提供了一個表編輯器,但內容編輯器通常希望更精美的東西。最常見的方法是:(1) 使用專用無頭式 CMS(如 Sanity 或 Storyblok)用於內容和 Supabase 用於應用數據,(2) 構建一個簡單的管理 UI,使用 Next.js + Supabase 身份驗證,或 (3) 將 WordPress 保持為無頭式 CMS 後端。對於以內容為重點的網站,選項 1 最受歡迎。如果你探索選項,我們在我們的 Astro 開發 和 無頭式 CMS 頁面上分解了權衡。
如果遷移出錯了怎麼辦——我能回滾到 WordPress 嗎? 是的,你應該規劃這個。在整個遷移過程中,在子域上執行你的 WordPress 網站。使用 DNS 級交換機(更改你的 A 記錄或 CNAME),所以你可以在幾分鐘內回滾。我們建議在啟動後至少 30 天保持舊 WordPress 實例執行。只有在確認所有重定向有效、搜索排名穩定且所有功能已驗證後才停用它。如果你想幫助規劃具有適當回滾程序的遷移,聯絡我們的團隊——我們已經做過足夠的次數,知道陷阱在哪裡。