iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0

昨天用 /init-theme 生出了骨架,但「會用指令」跟「看得懂它生了什麼」是兩回事。AI 幫你寫的程式碼,你還是得讀得懂,否則出問題時你連從哪查起都不知道。今天我們就打開這個真實的主題專案,把每個核心檔案一個個看過。

先看資料夾長相

block-theme/
├── style.css               # 主題檔頭 + 少量 CSS
├── theme.json              # 設計代幣的單一來源
├── functions.php           # 極少量的 PHP 接線
├── templates/              # 頁面層級模板(front-page / index / single / page / archive…,都是 .html)
├── parts/                  # 可重用片段(header.html、footer.html)
├── blocks/                 # 自訂區塊(hero、service-card、post-card…,後面幾天的主角)
├── patterns/               # 區塊版面配置
├── package.json            # 前端建置(@wordpress/scripts)
├── composer.json           # PHP 相依與指令
├── .phpcs.xml.dist         # 程式碼排版規則(WPCS)
├── phpstan.neon            # 靜態分析設定
├── phpunit.xml.dist        # 測試設定
├── tests/                  # 測試骨架(bootstrap.php、test-sample.php)
├── bin/                    # install-wp-tests.sh:建測試資料庫
├── scripts/                # build.php:打包 zip
├── languages/              # i18n(block-theme.pot)
├── readme.txt              # WordPress.org 格式的說明檔
└── .github/workflows/      # CI(release.yml,推 tag 自動發版)

對照傳統主題,你會發現一個很大的差異:沒有 single.phpheader.php 那些 PHP 模板了,取而代之的是 templates/parts/ 裡的 .html。範本階層還在(single.html 依然對應單篇文章、archive.html 對應封存頁),只是從「PHP 混 HTML」變成「純區塊標記」。

檔案分兩大類:style.csstheme.jsonfunctions.phptemplates/parts/blocks/主題本體,下半部那些 composer.json.phpcs.xml.dist.github/開發工具鏈。先看本體,最後再回頭認工具檔。

templates/:頁面骨架

打開 templates/front-page.html,內容長這樣:

<!-- wp:template-part {"slug":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
	<!-- wp:block-theme/hero {"align":"full"} /-->
	<!-- wp:block-theme/section-head {"eyebrow":"SERVICES","heading":"服務項目"} /-->
	...
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

看得出來,模板不再是寫 get_header()the_content() 這種 PHP 函式,而是一串區塊註解<!-- wp:... -->)。頂端用 wp:template-part 拉進 header,中間用 wp:group 當版面容器,裡面塞的 wp:block-theme/herowp:block-theme/section-head 就是我們自訂的區塊。整個頁面 = 區塊的堆疊。

拿傳統主題類比:front-page.html 就是 front-page.phpwp:template-part 就是 get_template_part(),概念一模一樣,只是語法從 PHP 換成區塊標記,而且能在站台編輯器裡用滑鼠改。像 index.html 這種文章列表頁,裡面則是一個 wp:query(Query Loop),等於傳統主題那個 while ( have_posts() ) 的迴圈,這之後會再詳細說明。

parts/:抽出來共用的片段

parts/header.htmlparts/footer.html 就是傳統主題的 header.phpfooter.php。全站每頁都要的東西:logo、選單、頁尾版權,抽成 part,模板用一行 wp:template-part 引用。改一次全站跟著變。

它用的是核心的 wp:site-logowp:site-titlewp:navigation 這些現成區塊,以前得在 header.php 裡寫 the_custom_logo()wp_nav_menu() 才生得出來。有個小坑要記得:part 不能放在子資料夾裡,一律平放在 parts/ 底下。

theme.json:全站設計的大腦

最關鍵的是 theme.json,傳統主題你在 functions.phpadd_theme_support()、在一大包 CSS 裡定義配色和字級;Block Theme 把這些全收斂進 theme.json

{
	"version": 3,
	"settings": {
		"layout": { "contentSize": "720px", "wideSize": "1140px" },
		"color": {
			"palette": [
				{ "name": "Primary", "slug": "primary", "color": "#ffd24d" },
				{ "name": "Accent", "slug": "accent", "color": "#f57c00" }
			]
		},
		"spacing": {
			"spacingSizes": [
				{ "slug": "60", "size": "2rem" },
				{ "slug": "80", "size": "6rem" }
			]
		}
	},
	"styles": {
		"elements": {
			"button": { "border": { "radius": "var(--wp--custom--radius--pill)" } }
		}
	}
}

分成兩大區塊:settings 決定「編輯器允許用什麼」(有哪些顏色、字級、間距可選),styles 決定「預設長什麼樣」(按鈕圓角、標題字體)。每個顏色、間距一旦在這裡定義,就自動變成一個 CSS 變數(var(--wp--preset--color--primary)),模板和區塊都引用它不用再各寫各的值。這就是所謂「單一來源」,想換全站主色,改這一行就好。

version 這裡是 3,是目前通用的 theme.json 結構版本,短期不用擔心它過期。

functions.php:保持精簡

傳統主題的 functios.php 動輒幾百行,Block Theme 只剩下幾件雜事:載入 text domain、把 style.css 掛進編輯器、註冊一個自訂的區塊分類,還有一段迴圈去註冊 blocks/ 底下的自訂區塊。

function block_theme_register_blocks() {
	$manifests = glob( get_template_directory() . '/build/blocks/*/block.json' );
	foreach ( $manifests as $manifest ) {
		register_block_type( dirname( $manifest ) );
	}
}
add_action( 'init', 'block_theme_register_blocks' );

大部分「以前寫在 functions.php 的設定」,都搬去 theme.json 了;PHP 只剩註冊和接線。這正是區塊主題對 AI 友善的原因之一:結構清楚、慣例固定,functions.php 不塞版面邏輯,AI 不容易寫歪。

把程式碼品質變成預設值

上一篇提到 /init-theme 除了主題本體還自動產生一整套「開發工具鏈」,工具說明如下:

檔案 角色
package.json 前端建置。用 @wordpress/scriptsblocks/ 裡的 JSX 編譯成瀏覽器能跑的 JS
composer.json / composer.lock 管 PHP 的開發相依(PHPCS、PHPStan、PHPUnit)與一組指令(composer phpcscomposer test⋯)
.phpcs.xml.dist 程式碼排版規則,用的是 WordPress Coding Standards(WPCS),跑 composer phpcs 時依它檢查
phpstan.neon 靜態分析設定。注意 paths 只掃 functions.php,因為 Block Theme 的 PHP 就這麼一點
phpunit.xml.disttests/ 測試設定與測試骨架(bootstrap.phptest-sample.php
bin/install-wp-tests.sh 建立跑測試用的 WordPress 測試資料庫
scripts/build.php 把主題打包成乾淨的 zip(composer build),輸出到 build/
.github/workflows/release.yml CI:推一個版本 tag 上 GitHub,自動打包發版
languages/block-theme.pot i18n 的翻譯範本,之後要出其他語系從它衍生
readme.txt WordPress.org 格式的說明檔(版本、相容性、標籤)

這些檔案「不是主題」,但它們決定了這個專案能不能長期維護,以及是否能安心讓 AI 大量產出,你不用每個都精通,只要知道它們在、出事時知道去哪查。一個判斷原則:templates/parts/theme.jsonfunctions.phpblocks/ 是主題本體,其餘多半是保持程式碼品質的工具鏈。

下一篇開始我們會在這個骨架上打造第一個自己的靜態區塊,從 block.json 這個「單一事實來源」講起。

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


上一篇
建立有程式碼品質約束的 WordPress 區塊主題骨架
下一篇
用 AI 打造第一個 WordPress 靜態 Block
系列文
從一句話到一個網站:用 Vibe Coding 開發 WordPress Block Theme 的 30 天18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言