iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0

前面我們從零做了一個完整的區塊佈景主題,但真實世界裡你手上更可能是一個跑了三年的傳統佈景主題:header.phpsingle.php、一支兩千行的 style.cssfunctions.php 塞滿了各種 hook。客戶不會給你打掉重練的預算,你也不敢一次全換。

這篇講漸進遷移,重點不是「怎麼把舊主題改成新主題」,而是怎麼分階段讓每一步都能單獨上線,隨時停在中間也不會壞

傳統佈景主題三階段移轉

很多人以為「區塊佈景主題」是一個要嘛全有、要嘛全無的狀態,實際看 WordPress 核心的判定,會發現至少有三個獨立的開關:

開關 判定依據 打開之後
讀不讀 theme.json 檔案存不存在 外觀選單的「區塊版面配置」變成「設計」
吃不吃 HTML 範本 current_theme_supports( 'block-templates' ) templates/*.html 開始參與範本階層
是不是區塊佈景主題 templates/index.html 存不存在 網站編輯器全開,PHP 範本全面停用

這三個開關可以分開打開,中間的每一個狀態都是合法的、可以上線的。整個遷移策略就建立在這件事上。

第零步:先盤點舊主題有什麼

動手之前先盤點以下四類:

  1. 範本檔header.phpfooter.phpsingle.phparchive.php… 哪些真的有人用,哪些是三年前複製來就沒動過的
  2. functions.php 的內容add_theme_support 開了什麼、enqueue 了什麼、掛了哪些 hook
  3. 寫死的設計值style.css 裡出現過幾種顏色、幾種字級、幾種間距
  4. 選單與小工具區register_nav_menusregister_sidebar 註冊了哪些

第 3 項最適合交給 AI,做法跟 everything-wp 的 make-block 指令是同一套思路,只是掃描對象從別人的網站換成自己的舊 CSS,可以請它把所有色碼列出來、依出現次數排序、把相近的分群,最後產出一份「原始值 → 建議語意名稱」的對照表。

階段一:先加 theme.json,主題還是傳統主題

第一步只做一件事:把散在 CSS 裡的顏色、字級、間距彙整起來寫進 theme.json

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {
    "color": {
      "palette": [
        { "slug": "primary",  "color": "#ffd24d", "name": "Primary" },
        { "slug": "contrast", "color": "#060606", "name": "Contrast" }
      ]
    },
    "spacing": { "spacingSizes": [ … ] },
    "typography": { "fontSizes": [ … ] }
  }
}

這一步的風險極低,因為前台外觀不會變。你的 style.css 還在原地跑,theme.json 只是多提供了一組變數,這樣整理後有兩個好處:

第一個是區塊編輯器的顏色與字級面板會跟設計對齊,編輯不再從無限色盤裡挑一個接近的顏色。第二個比較意外:後台「外觀」選單底下原本那個「區塊版面配置」,會變成「設計」,傳統佈景主題只要有 theme.json,就能進網站編輯器看樣式手冊(Style Book):

這個樣式手冊是唯讀的,你在裡面改不了任何東西,換句話說,加 theme.json 換到的是「看得到」不是「改得動」,要調預設樣式仍然只有改 theme.json 一途,要能在後台改,得等到階段三把主題變成真正的區塊佈景主題才行。

另一個好處是只要主題有 theme.jsonWordPress 就自動開啟 block-templates 支援,也就是說你放進 templates/ 的 HTML 範本從這一刻起就會生效了,不需要另外宣告什麼。

階段二:混合式主題,先把頁首頁尾交出去

第二步是把 header.phpfooter.php 改成可以在網站編輯器裡編的區塊範本組件。先宣告支援:

add_theme_support( 'block-template-parts' ); // WP 6.1 起.

接著建 parts/header.html,內容就是區塊標記:

<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
  <!-- wp:site-logo /-->
  <!-- wp:site-title /-->
  <!-- wp:navigation /-->
</div>
<!-- /wp:group -->

然後把 header.php 的內容換掉:

<?php
// 舊的:一堆 HTML 加 wp_nav_menu().
// 新的:把頁首交給區塊範本組件.
block_header_area();

block_header_area()block_footer_area() 是 WordPress 5.9 就有的函式(wp-includes/block-template-utils.php),底層都是 block_template_part( $part ),可以印出任何一個 parts/*.html

做完這一步,網站擁有者已經可以在後台改頁首頁尾了,而其他頁面仍然由你的 PHP 範本渲染。主題到這裡還不是區塊佈景主題,wp_is_block_theme() 仍然回傳 false

我建議從頁首頁尾開始,是因為它們是全站共用、改動效益最大,而且結構相對單純(logo、選單、幾個連結),翻成區塊標記的風險比 single.php 那種帶迴圈與條件判斷的低很多。

階段三:逐個換範本,最後才放 index.html

第三步才開始動範本,而且可以一個一個換。能這樣做的原因在 locate_block_template()

// wp-includes/block-template.php
function locate_block_template( $template, $type, array $templates ) {
	if ( ! current_theme_supports( 'block-templates' ) ) {
		return $template;
	}

	if ( $template ) {
		// locate_template() 已經找到一個 PHP 範本,
		// 所以只考慮「specificity 高於或等於它」的區塊範本.
		$index     = array_search( $relative_template_path, $templates, true );
		$templates = array_slice( $templates, 0, $index + 1 );
	}

	$block_template = resolve_block_template( $type, $templates, $template );
	…
}

看懂這段就懂了整個策略:PHP 範本和 HTML 範本可以共存。WordPress 先照傳統的範本階層找到 PHP 範本,再看有沒有同樣(或更精確)的區塊範本可以取代它。你放了 templates/single.html,single 就走區塊範本;沒放 templates/archive.html,archive 就繼續用 archive.php

所以要遷移的話建議是從流量低、結構單純的開始:

  1. 404.phptemplates/404.html(幾乎沒有邏輯,最好練手)
  2. search.phparchive.php → 用 Query Loop 取代 The Loop
  3. page.phpsingle.php → 帶精選圖片、meta、留言的,最複雜
  4. front-page.php → 首頁通常最多客製,留到最後

每換一個就部署觀察一段時間,出事只會出在那一種頁面,回退也只要刪掉那一個 HTML 檔。

最後才處理 index.html,因為它是那個總開關:

// wp-includes/class-wp-theme.php
public function is_block_theme() {
	$paths_to_index_block_template = array(
		$this->get_file_path( '/templates/index.html' ),
		$this->get_file_path( '/block-templates/index.html' ),
	);
	…
}

is_block_theme() 只看這個檔案存不存在。放上去的那一刻,主題正式成為區塊佈景主題:網站編輯器全開、所有 PHP 範本停止作用。所以這一步等於「確認前面每一個範本都已經有 HTML 版本」的最終驗收,不要提早放。

遷移路上最容易出事的三件事

一、掛在 wp_headget_header 上的邏輯。 區塊佈景主題沒有 header.phpget_header() 不會執行,掛在 get_header 這個 action 上的東西就跟著消失。wp_head 本身還在(範本渲染時仍會呼叫),但那些「假設一定會經過 header.php」的程式碼要一個個確認。這是遷移時最常見的「東西不見了但沒有錯誤訊息」。

二、選單的資料搬遷。 wp_nav_menu() 讀的是 nav_menu 分類法,Navigation 區塊存的是自己的區塊標記(在 wp_navigation 這個文章類型裡),兩者資料結構不同不會自動同步。第一次插入 Navigation 區塊時,編輯器會提供從既有選單匯入的選項,用它匯一次,之後就以區塊那份為準,舊選單留著不會有作用。

三、小工具區。 register_sidebar 註冊的側邊欄在區塊佈景主題裡沒有位置,內容要改放進範本或範本組件,如果客戶習慣自己拖小工具,這件事要先講清楚,因為這是操作習慣的改變,不是技術問題。

這段路 AI 能幫什麼

最適合交給 AI 的有三件:

  1. 把舊 CSS 抽成設計屬性:掃 style.css 列出所有色碼與尺寸、分群、命名,產出 theme.json
  2. 把 PHP 範本翻成區塊標記single.php 裡的 The Loop 對應 Query Loop、the_post_thumbnail() 對應 Post Featured Image 區塊,這種一對一的翻譯它做得又快又準。
  3. 盤點 hook 相依:請它掃 functions.php,列出所有掛在 get_headerget_footerget_sidebar 上的函式,那就是上一節第一個坑的清單。

而你要自己判斷的是這幾件:遷移順序怎麼排、哪些舊功能趁這次直接放棄、客戶的哪些操作習慣需要事先溝通、以及什麼時候按下 index.html 那個開關。這些都不是技術題,是專案判斷。

還有一個要提醒的:不要讓 AI 一次把整個主題做遷移。 它能做到,但你會拿到一個無法逐步驗證的大改動,出事時不知道是哪一步壞的,一次一個範本,換完部署,看兩天,再換下一個。漸進遷移的價值就在這裡,別為了快而放棄它。

遷移 vs. 打掉重練

雖然有 AI 協助但要完成遷移還是一項滿費工的作業,另一條路是把舊網站當成設計稿,用之前介紹的流程重新做一個區塊佈景主題,做好之後切換。

這兩條路的差別在成本什麼時候發生、風險集中在哪裡

漸進遷移 照舊站重做
成本發生的時間 分散在每個階段 集中在上線前
何時看得到成果 加完 theme.json 就有 全部做完才有
上線風險 一次換一個範本,可單獨回退 一次性切換,風險集中在同一天
舊技術債 跟著搬過去 這是清掉它的唯一機會
設計一致性 從舊 CSS 反推,容易連原本的不一致一起繼承 從第一天就是單一來源
PHP 客製(WooCommerce 範本覆蓋、會員、自訂查詢) 可以先留著,慢慢處理 要重寫一遍
中途可以停嗎 可以,混合式主題本身就是合法狀態 不行,沒有中間狀態
長期維護成本 較高,可能長期維持兩套邏輯 較低

**選漸進遷移:**如果站台正在營運而且不能停、舊主題有大量 woocommerce/ 範本覆蓋或會員邏輯、預算需要分批處理,這些情境的共同點是「不能出事」比「做得漂亮」重要。

**打掉重練:**如果那支 style.css 已經爛到沒人敢動、設計本來就要順便翻新、舊主題的 PHP 客製其實不多(只是版面)、或者這個站你要長期維護下去。共同點是「以後每次改動都會受益」的情境。

有一個判準我覺得特別好用:問自己「舊主題裡有多少東西是我想留的」。如果答案是「版面和配色要留,程式碼一行都不想留」,那你要的其實是重做,只是用舊站當設計稿而已。

AI 讓天平往重做那邊偏了一點

過去重做的成本高得嚇人,因為要重看設計、重刻 CSS、重建整套元件。但上一篇那條流程改變了計算方式:/make-block 接受的輸入就是一個網址,而你的舊網站就是一個現成的網址

/make-block https://your-old-site.com

它會掃過舊站的每個代表頁、抽出實際的 computed style、盤點元件清單,然後生成 theme.json 與一整組區塊,換句話說,「照舊站重做」以前是一個月的工作,現在前面 80% 是自動的,你的工作變成審 UI Library 那一頁、把不對的地方挑出來。

所以如果你三年前評估過「重做太貴」而選擇了將就,現在值得重新評估一次。

實務上可以這樣做:兩條路混著走

老實說我自己的做法不是二選一,而是用重做的方式產生資產,用遷移的節奏上線

  1. 先對舊站跑一次 /make-block,拿到乾淨的 theme.json 與一整組區塊 — 這是重做的產物,沒有繼承舊 CSS 的歷史包袱
  2. 不要一次換掉整個主題。把產出的 theme.json 與區塊放進舊主題裡,然後照本篇的三個階段,一個範本一個範本替換
  3. 每換一個就部署、觀察,最後才放 templates/index.html

這樣前面拿到重做的乾淨資產,後面保留遷移的低風險節奏。代價是中間那段時間你要同時看著兩套東西,但比起「一次性切換的那一天」,我寧願分散這個壓力。

最後補一個誠實的提醒:漸進遷移最大的風險,是中間狀態變成永久狀態。 混合式主題可以跑得很好,好到你永遠不會去按 index.html 那個開關,於是三年後這個主題還是一半 PHP 一半 HTML,新來的人看不懂它到底是哪一種。要避免這件事,開始遷移的時候就把最後一步排進行事曆,而不是等「有空的時候」。

下一篇我們介紹如何用 AI 跑完程式碼規範、靜態分析、測試與多語系這四道關卡,把主題整理到可以交付的狀態。

文章目錄:https://oberonlai.blog/category/2026-ithome/


上一篇
用 make-block 把 WordPress 區塊變成完整網站
下一篇
WordPress 開發的品質檢測:PHPCS、PHPStan、PHPUnit 與 i18n
系列文
從一句話到一個網站:用 Vibe Coding 開發 WordPress Block Theme 的 30 天29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言