Sanity 遷移手冊:從 WordPress、Contentful 或 Drupal 轉移
Sanity 遷移手冊:從 WordPress、Contentful 或 Drupal 遷移
在過去三年中,我已將大約 40 個項目遷移到 Sanity。有些是乾淨的兩週衝刺。其他的則變成了三個月的苦差事,讓我質疑自己的職業選擇。差異幾乎從不取決於源 CMS — 而是取決於準備、內容建模決策,以及對你實際簽署的內容有誠實的了解。
這是我開始進行 CMS 遷移時希望擁有的指南。它涵蓋從 WordPress、Contentful 和 Drupal 遷移到 Sanity GROQ 驅動的世界。我將坦誠地說明 Sanity 的優勢、可能會讓你感到沮喪的地方,以及實際的時間表是什麼樣的。
目錄
- 為什麼團隊在 2025 年遷移到 Sanity
- 遷移前審計:每個人都跳過的步驟
- WordPress 到 Sanity 遷移
- Contentful 到 Sanity 遷移
- Drupal 到 Sanity 遷移
- 內容建模:正確獲取你的架構
- 數據遷移策略和工具
- 沒有人談論的隱藏成本
- 遷移後檢查清單
- 時間表和預算比較
- 常見問題

為什麼團隊在 2025 年遷移到 Sanity
讓我們先講明白顯而易見的事情。Sanity 的實時協作編輯、可自定義的 Studio 和結構化內容方法確實很好。但大多數團隊與我們聯繫進行遷移的原因不是因為他們讀了一篇關於 Sanity 功能的博客文章。這是因為出了問題。
WordPress 站點在具有複雜自定義文章類型的 50,000 多個內容中命中擴展牆。Contentful 的定價模式在企業層級開始受到擠壓 — 我們已看到團隊面臨 $3,500+/月的帳單,相當於一個內容 API。Drupal 團隊找不到開發人員了,至少找不到想在 2025 年使用 PHP 模板的開發人員。
Sanity 的定價模型對大多數團隊來說確實更可預測。免費層級涵蓋每月高達 100K API 請求和 500K 資產。Growth 計畫每月 $99/個項目可讓你獲得 2.5M API 請求和 1M 資產。相比之下,Contentful 的 Team 計畫運行 $300/月,Contentful 的 Premium 層級可輕鬆超過 $2,000/月。
但以下是我的誠實看法:如果你目前的 CMS 運行良好,你的團隊富有成效,就不要只因為 Sanity 更新或更酷就進行遷移。遷移的成本總是比你想的要高。
遷移前審計:每個人都跳過的步驟
在你寫一行遷移代碼之前,你需要進行內容審計。不是快速掃描 — 真正的審計。以下是外觀:
內容清單
記錄每種內容類型、每個欄位、每個關係。我使用帶有以下列的電子表格:
- 內容類型名稱
- 總項目數
- 欄位(帶類型)
- 與其他內容類型的關係
- 媒體附件(計數和總大小)
- 自定義功能(短代碼、小部件、嵌入)
- 上次修改日期
- 仍然相關?(是/否/可能)
你會對有多少內容是死權重感到震驚。在一次 WordPress 遷移中,一個客戶有 12,000 篇文章。審計後,只有 4,200 篇仍然相關。這是 65% 的內容減少要遷移、測試和驗證。
技術依賴性映射
列出你目前的 CMS 使用的每個插件、模組或集成。對於每一個,確定:
- Sanity 能否原生處理這個?
- Sanity 是否有插件?
- 我們需要建立自定義解決方案嗎?
- 我們能完全放棄這個嗎?
這個映射本身將在未來為你節省數週的驚喜。
團隊準備情況評估
Sanity Studio 基於 React。你的內容編輯將需要培訓。你的開發人員將需要學習 GROQ(或使用 GraphQL,雖然 GROQ 是 Sanity 真正閃耀的地方)。為團隊入職預算 1-2 週 — 不是作為錦上添花,而是作為一個訂單項。
WordPress 到 Sanity 遷移
WordPress 是我們從中遷移最常見的源 CMS。這也是最棘手的,因為 WordPress 不僅是一個 CMS — 它是一個整個應用程式平台,人們已經將所有東西都集成到其上。
什麼轉移得很乾淨
- 文章和頁面(基本內容)
- 分類和標籤
- 精選圖像
- 作者數據
- 基本自定義欄位(ACF、Meta Box)
什麼變得混亂
- Gutenberg 塊:每種塊類型都需要對應的 Sanity Portable Text 自定義塊或對象類型。如果你有 15 多個自定義 Gutenberg 塊,請為此預算重要時間。
- 短代碼:這些需要被解析、解釋,並轉換為 Portable Text 註釋或自定義塊。WPBakery 和 Elementor 短代碼尤其令人痛苦。
- 插件生成的內容:WooCommerce 產品、Yoast SEO 數據、ACF 重複器欄位 — 每一個都需要自定義遷移邏輯。
- 媒體庫:WordPress 存儲多個圖像大小。Sanity 即時處理圖像轉換,因此你只需要原始圖像。但在混亂的 wp-uploads 資料夾中找到原始圖像?有趣的時光。
遷移腳本方法
我通常使用命中 WordPress REST API 並寫入 Sanity 變更 API 的 Node.js 腳本:
import { createClient } from '@sanity/client'
import fetch from 'node-fetch'
const sanity = createClient({
projectId: 'your-project-id',
dataset: 'production',
token: process.env.SANITY_WRITE_TOKEN,
apiVersion: '2025-01-01',
useCdn: false,
})
const WP_API = 'https://yoursite.com/wp-json/wp/v2'
async function migratePosts(page = 1) {
const res = await fetch(`${WP_API}/posts?per_page=100&page=${page}`)
const posts = await res.json()
const totalPages = res.headers.get('x-wp-totalpages')
const transaction = sanity.transaction()
for (const post of posts) {
transaction.createOrReplace({
_id: `wp-post-${post.id}`,
_type: 'post',
title: post.title.rendered,
slug: { current: post.slug },
publishedAt: post.date,
// Body requires HTML-to-Portable-Text conversion
body: await convertToPortableText(post.content.rendered),
})
}
await transaction.commit()
console.log(`Migrated page ${page} of ${totalPages}`)
if (page < totalPages) {
await migratePosts(page + 1)
}
}
convertToPortableText 函數是 80% 複雜性所在的地方。我使用 @sanity/block-tools 包結合 jsdom 進行 HTML 解析。它很好地處理基本 HTML,但自定義元素和短代碼需要單個處理程序。
現實時間表
對於一個典型的 WordPress 站點,有 500-2,000 篇文章、標準自定義欄位和少數自定義文章類型:4-8 週,包括內容建模、遷移腳本、驗證和編輯器培訓。

Contentful 到 Sanity 遷移
Contentful 到 Sanity 實際上是三個中最順暢的遷移路徑。為什麼?因為兩者都是具有相似心智模型的結構化內容平台。你的內容已經在無頭 CMS 中,具有定義的內容類型和欄位。
需要考慮的主要差異
| 功能 | Contentful | Sanity |
|---|---|---|
| 富文本 | Rich Text(基於 JSON) | Portable Text(基於 JSON) |
| 內容建模 | Web UI | 代碼定義的架構 |
| 查詢語言 | GraphQL / REST | GROQ(+ GraphQL) |
| 本地化 | 內置的欄位級別 | 插件或自定義 |
| 引用 | 鏈接(Entry/Asset) | 帶類型的引用 |
| Webhooks | 是 | 是 |
| 資產處理 | 內置 CDN | Sanity CDN + 熱點/裁剪 |
| 定價(中層) | ~$300/月(Team) | $99/月(Growth) |
富文本轉換
Contentful 的 Rich Text 和 Sanity 的 Portable Text 都是基於 JSON 的,這很好。但它們具有不同的結構。你需要編寫轉換器:
function contentfulRichTextToPortableText(richTextField) {
return richTextField.content.map(node => {
switch (node.nodeType) {
case 'paragraph':
return {
_type: 'block',
style: 'normal',
children: node.content.map(mapInlineContent),
}
case 'heading-2':
return {
_type: 'block',
style: 'h2',
children: node.content.map(mapInlineContent),
}
case 'embedded-entry-block':
// Map to your custom Portable Text type
return mapEmbeddedEntry(node)
// ... handle all node types
}
}).filter(Boolean)
}
內容類型到架構映射
Contentful 內容類型相當直接映射到 Sanity 文檔和對象類型。最大的轉變是 Sanity 架構在代碼(JavaScript/TypeScript)中定義,而不是在 Web UI 中。這實際上是一個巨大的優勢 — 你的內容模型存活在版本控制中。
使用 Contentful Management API 導出你的內容模型,然後編寫生成 Sanity 架構文件的腳本:
contentful space export --space-id YOUR_SPACE_ID --export-dir ./export
現實時間表
對於具有 10-20 個內容類型和 5,000-10,000 個條目的 Contentful 空間:3-5 週。它更快,因為你已經在以結構化內容的方式思考。
Drupal 到 Sanity 遷移
Drupal 遷移是讓我倒第二杯咖啡的那些。不是因為 Drupal 不好 — 它是一個強大的系統。但 Drupal 站點傾向於很舊、自定義過度,並在沒有人完全理解的基礎設施上運行。
Drupal 特定的挑戰
- 內容類型有 50+ 個欄位:Drupal 使添加欄位變得容易。太容易了。我見過有 80 個欄位的內容類型,其中一半未使用。
- 分類項引用:Drupal 的分類系統是靈活的,但可以創建需要為 Sanity 展平的深層嵌套層次結構。
- Paragraphs 模組:如果站點使用 Drupal Paragraphs(大多數現代 Drupal 站點都這樣做),每種段落類型都變成 Portable Text 塊類型或 Sanity 對象。這是最大的單一任務。
- 媒體實體:Drupal 9/10 的媒體系統比 WordPress 更複雜。多個媒體類型、可重複使用的媒體實體和文件欄位配置都需要映射。
- 多語言內容:Drupal 的翻譯系統是複雜的。Sanity 在相同級別上沒有內置本地化 — 你將需要
@sanity/document-internationalization插件或欄位級別的方法。
遷移方法
我偏好使用 Drupal 的 JSON:API 模組(自 Drupal 9.x 以來包含在 Drupal 核心中)作為提取層:
async function fetchDrupalContent(type, page = 0) {
const limit = 50
const offset = page * limit
const url = `${DRUPAL_URL}/jsonapi/node/${type}?page[limit]=${limit}&page[offset]=${offset}&include=field_image,field_paragraphs`
const res = await fetch(url, {
headers: { Authorization: `Basic ${DRUPAL_AUTH}` },
})
return res.json()
}
對於沒有 JSON:API 的較舊 Drupal 7 站點,你可能需要直接查詢數據庫。Drupal 7 的數據庫架構是…一種經驗。field_data_* 表將困擾你的夢想。
現實時間表
Drupal 遷移差異很大。一個直接的 Drupal 10 站點,有 5-10 個內容類型:5-8 週。一個具有 30+ 個內容類型、Paragraphs 和多語言內容的舊版 Drupal 7 站點:8-16 週。我沒有誇大。
內容建模:正確獲取你的架構
以下是大多數遷移指南不會告訴你的事情:不要在 Sanity 中複製你的舊內容模型。這是你修復多年累積內容債務的機會。
常見建模錯誤
- 創建 1:1 欄位映射:WordPress 有「副標題」自定義欄位的事實並不意味著 Sanity 需要一個。也許它應該是結構化「hero」對象的一部分。
- 過度嵌套對象:Sanity 允許你深層嵌套對象。抵制誘惑。平坦的架構更容易用 GROQ 查詢,編輯也更容易使用。
- 忽視 Portable Text 的力量:不要只是將 HTML 轉儲到單個文本欄位中。設計與你的內容模式匹配的自定義塊類型。一個「呼號」塊、一個「代碼片段」塊、一個「帶標題的圖像」塊 — 這些使編輯的生活更輕鬆。
架構設計過程
我遵循這個順序:
- 審計現有內容(在遷移前完成)
- 識別實際內容模式(不是 CMS 強加的)
- 在紙上/白板上先設計架構
- 在代碼中構建架構
- 導入小型測試批次(50-100 項)
- 讓編輯測試 Studio 體驗
- 在完全遷移之前迭代架構
步驟 5-7 至關重要,通常被跳過。我們已經在我們的無頭 CMS 開發工作中編寫了更多關於內容建模方法的內容。
數據遷移策略和工具
必要工具
@sanity/client:用於讀取/寫入 Sanity 數據的官方 JavaScript 客戶端@sanity/block-tools:將 HTML 轉換為 Portable Textsanity dataset import/export:用於完整數據集操作的 CLI 工具ndjson:Sanity 使用換行符分隔的 JSON 進行導入 — 熟悉它jsdom或htmlparser2:用於富文本轉換期間的 HTML 解析
遷移架構
我將每次遷移構建為具有四個階段的管道:
Extract → Transform → Load → Validate
每個階段都是一個單獨的腳本。這很重要,因為你將運行遷移多次 — 通常在最終生產運行之前 5-10 次。擁有單獨的階段意味著你只能重新運行需要修復的部分。
# Extract
node scripts/extract-wordpress.js > data/raw-posts.ndjson
# Transform
node scripts/transform-posts.js < data/raw-posts.ndjson > data/sanity-posts.ndjson
# Load
sanity dataset import data/sanity-posts.ndjson production --replace
# Validate
node scripts/validate-migration.js
處理資產
圖像和文件總是最慢的部分。Sanity 的資產管道很好,但上傳 10,000 張圖像需要時間。提示:
- 先上傳資產,維護舊 URL 到新 Sanity 資產 ID 的映射
- 使用並發上傳(但尊重速率限制 — 增長計畫為 25 req/秒)
- 驗證上傳前的圖像尺寸和格式
- 不要遷移縮圖大小 — Sanity 通過其圖像 CDN 即時生成這些
沒有人談論的隱藏成本
讓我坦誠地告訴你不會出現在典型遷移估計中的成本。
URL 重定向
如果你改變前端(如果你遷移到無頭 CMS,你可能會這樣做),你需要重定向映射。每。一。個。URL。對於 SEO,這是非強制的。一個有 5,000 頁的站點需要 5,000 個重定向規則。像 next.config.js 重定向或 Vercel 的 _redirects 文件這樣的工具可以處理這個問題,但有人必須建立映射。
SEO 元數據遷移
來自 WordPress 的 Yoast SEO 數據。來自 Drupal 的 Metatag 模組數據。Contentful 的 SEO 欄位。所有這些都需要出現。自定義元標題、描述、Open Graph 圖像、規範 URL、結構化數據 — 這是項目中的一個項目。
編輯器培訓和文檔
最少預算 2-4 天。Sanity Studio 很直觀,但不同於你的編輯所知道的。我們通常創建帶有屏幕截圖的自定義 Studio 文檔,並錄製 3-5 個演練視頻。
前端開發
這是房間裡的大象。將內容遷移到 Sanity 只是項目的一半。你還需要一個消費內容的前端。無論你是使用 Next.js、Astro 還是另一個框架,前端構建通常是總項目成本的 50-70%。如果你正在評估前端選項,請查看我們的 Next.js 和 Astro 工作。
時間表和預算比較
基於我們在 2024-2025 年完成的項目:
| 遷移路徑 | 內容量 | 複雜性 | 時間表 | 預算範圍 |
|---|---|---|---|---|
| WordPress → Sanity | < 1,000 頁 | 低 | 3-5 週 | $8K-$15K |
| WordPress → Sanity | 1,000-10,000 頁 | 中等 | 6-10 週 | $15K-$35K |
| WordPress → Sanity | 10,000+ 頁 | 高 | 10-16 週 | $35K-$75K |
| Contentful → Sanity | < 5,000 條目 | 低-中等 | 3-5 週 | $7K-$18K |
| Contentful → Sanity | 5,000-20,000 條目 | 中等 | 5-8 週 | $18K-$40K |
| Drupal → Sanity | < 2,000 節點 | 中等 | 5-8 週 | $12K-$25K |
| Drupal → Sanity | 2,000-15,000 節點 | 高 | 8-14 週 | $25K-$60K |
| Drupal 7 → Sanity | 任何 | 非常高 | 10-20 週 | $35K-$90K |
注意:這些範圍僅包括內容遷移。前端開發是額外的。有關特定項目的估計,請聯繫我們 /pricing。
這些數字包括內容建模、遷移腳本、數據驗證和基本編輯器培訓。它們不包括前端開發、設計或持續維護。
遷移後檢查清單
這是我在每次遷移上使用的檢查清單:
- 所有內容類型遷移並驗證
- 所有引用/關係完整
- 所有圖像和文件上傳並正確鏈接
- 富文本內容正確呈現(檢查格式破裂)
- URL 重定向到位並測試
- SEO 元數據遷移(標題、描述、OG 數據)
- XML 網站地圖重新生成
- 搜索控制台使用新網站地圖更新
- 分析追蹤保留
- 編輯器帳戶已建立並設置權限
- 編輯器培訓完成
- 內容預覽(草稿模式)工作
- 為構建觸發器配置的 Webhooks
- 源 CMS 數據的備份存檔
- DNS 更改已計畫(如適用)
- 性能基準測量
- 前 30 天設置了 404 監控
最後一點很重要。無論你的重定向映射多麼徹底,一些 URL 都會滑過去。在第一個月積極監控你的 404。
常見問題
典型的 WordPress 到 Sanity 遷移需要多長時間? 對於一個標準 WordPress 站點,有不到 2,000 篇文章和直接的自定義欄位,預期 4-8 週。這包括內容建模、遷移腳本、數據驗證和編輯器培訓。具有複雜 Gutenberg 塊、WooCommerce 或多語言內容的站點可能需要 10-16 週。內容量不如內容類型的複雜性重要。
我可以從 Contentful 遷移到 Sanity 而不會丟失數據嗎? 是的,實際上這是我在這裡介紹的三個中最乾淨的遷移路徑。兩個平台都使用結構化、基於 JSON 的內容,因此映射相對直接。富文本需要從 Contentful 的格式轉換為 Portable Text,並且引用需要重新映射,但你不應該丟失任何數據。我建議先針對預備數據集運行遷移,並在切換前進行徹底的內容比較。
在 CMS 遷移期間我的 SEO 排名會發生什麼? 這是讓營銷總監夜不能寐的問題。如果你正確處理重定向、盡可能保持你的 URL 結構,並遷移所有 SEO 元數據,你應該看到最小的影響。Google 自己的文檔說,正確重定向的遷移可能會看到 2-4 週的臨時下降,然後恢復。關鍵詞是「適當」。跳過重定向映射,你將摧毀你的排名。我們已經看過它發生。
Sanity 對企業使用來說比 Contentful 更便宜嗎? 在大多數情況下是的 — 有時顯著。Sanity 的 Growth 計畫每月 $99 覆蓋你所需的 Contentful 每月 $300 Team 計畫所需的內容。在企業規模,差異變大。Contentful 的 Premium 定價未公開列出,但通常運行 $2,000-$4,000+/月。Sanity Enterprise 定價也是自定義的,但通常對等效使用量來說較低。真正的成本差異在於 API 呼叫 — Sanity 的包含限制更慷慨。
我應該將我的 Drupal 7 站點遷移到 Sanity 還是首先升級到 Drupal 10? 直接進入 Sanity。從 Drupal 7 遷移到 Drupal 10 的工作量幾乎與遷移到不同的 CMS 一樣多 — 版本之間的架構改變那麼激烈。如果你已經投資大遷移,你可能也應該遷移到你長期實際想要的平台。一個例外:如果你的團隊深度投入 Drupal 生態系統,只是想現代化,Drupal 10 加上無頭前端是一個有效的路徑。
遷移到 Sanity 時我需要重建我的前端嗎? 如果你來自像 WordPress 或 Drupal 這樣的整體式 CMS,是的 — 你將需要一個新前端,因為 Sanity 是無頭的。這通常是項目的更大部分。如果你來自 Contentful,你通常可以重複使用你現有的前端,修改 API 呼叫,特別是如果你已經在使用 Next.js 或類似框架。我們將 CMS 遷移和前端構建作為集成項目處理。
我可以在遷移期間並行運行舊 CMS 和 Sanity 嗎? 絕對可以,我推薦這樣做。在初始遷移後並行運行兩個系統 2-4 週。編輯可以繼續在舊 CMS 中工作,同時你在 Sanity 中驗證數據。只需在最終遷移運行之前在舊系統中凍結內容 — 你不想追逐一個移動的目標。有些團隊在最終轉換前 48 小時設置「內容凍結」日期。
團隊在 Sanity 遷移期間犯的最大錯誤是什麼? 試圖在 Sanity 中精確複製他們舊 CMS 結構。我經常看到這個。團隊來自 WordPress 並試圖在 Sanity 中建立 WordPress 形狀的架構 — 通用「頁面」類型具有靈活的佈局,而不是目的構建的內容類型。Sanity 的強項是結構化內容。利用遷移作為正確建模內容的機會。在內容建模上多花一週。以後會為你節省數月的痛苦。如果你想要指導,聯繫我們 — 內容建模是我們在遷移項目中花費最多時間的事情之一。