Communitygithub.com

sijad/astro-wordpress

將靜態 Astro 模板轉換為 WordPress 主題 — 安裝適配器、設定 astro.config.mjs、加入主題 style.css、將頁面轉換為 .php.astro,並可選擇透過 Docker Compose 執行 WordPress。

astro-wordpress 是什麼?

這個技能提供了一個經過實戰驗證的逐步指南,使用 `astro-wordpress` 適配器將靜態 Astro 網站轉換為可運行的 WordPress 主題。它涵蓋了安裝、設定、將 `.astro` 頁面轉換為 `.php.astro` 檔案以及產生可啟用的主題等步驟。該指南支援兩種本機 WordPress 環境:透過 Docker Compose(推薦,無需本機 PHP/MySQL/wp-cli)或已存在的本機 WordPress 安裝。對於 Docker 設置,它還包括一個完整的 `compose.yaml` 檔案和用於無頭測試的指令。此技能明確僅涵蓋基本適配器設定;若需使用 ACF 使主題內容可透過 WP 後台編輯,請參閱相關的 `astro-wordpress-acf` 技能。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sijad/astro-wordpress/tree/HEAD/skills/astro-wordpress

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

透過 astro-wordpress 將靜態 Astro 模板轉換為 WordPress 主題:src/pages/*.php.astro 下的頁面會編譯成真正的 WordPress 模板檔案(index.php、page-template-*.php、……),而 npm run dev 則會代理到本機的 WordPress 實例,以便主題能隨時與其進行即時預覽。

這是經過驗證的準則,並非對適配器 README 的改寫:下列步驟已套用於一個真實的靜態 Astro 模板,並從頭到尾確認有效 — 開發伺服器代理能即時通往 WordPress,npm run build 能產出真正的可啟用主題,wp theme activate 也能成功執行。

先決條件

  • 一個可透過 HTTP 存取的本機 WordPress 安裝。兩個經過驗證的選項:
    • Docker Compose(推薦 — 完全不需要本機 PHP/MySQL/wp-cli,且主機上可能根本沒安裝 wp-cli)。請參閱步驟 0。
    • 一個正在執行的本機 WP 安裝(任何 PHP 伺服器 + MySQL/MariaDB,並由 devProxyTarget 指向)。無論如何,此技能僅轉換 Astro 端。
  • 用於 Astro 專案的 Node/npm。
  • wp-cli 在此技能中完全為選用 — 下方每個 wp-cli 指令都有無 wp-cli 的替代方案(瀏覽器/curl 表單提交,或容器化的 wp-cli 輔助容器)。請勿將其設為硬性需求。

0. (Docker 選項) 使用 Docker Compose 啟動 WordPress

這個來自 astro-wordpress 起手版的 compose.yaml 可直接使用且無需修改 — 經過實際執行驗證:

services:
  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8088:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - ./wp:/var/www/html
      - ./public/:/var/www/html/public

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: "1"
    volumes:
      - db:/var/lib/mysql

volumes:
  db:
docker compose up -d

wordpress 映像檔預設沒有 wp-cli — 請透過瀏覽器 (http://localhost:8088) 完成安裝及其他所有操作,或使用一次性容器化的 wp-cli 容器,該容器共用相同的網路和磁碟區(請參閱驗證/注意事項 — 每當下方步驟提到 wp ... 且本機未安裝 wp-cli 時,都應採用此模式):

docker run --rm --network container:<wordpress-container-name> \
  --volumes-from <wordpress-container-name> -w /var/www/html \
  -e WORDPRESS_DB_HOST=db -e WORDPRESS_DB_USER=exampleuser \
  -e WORDPRESS_DB_PASSWORD=examplepass -e WORDPRESS_DB_NAME=exampledb \
  wordpress:cli <wp-cli-command>

(-e 變數必須與 wordpress 服務的環境變數相符 — CLI 容器會讀取同一個 wp-config.php,後者透過 getenv() 解析這些變數,但不會繼承另一個容器的環境變數。)

步驟

1. 安裝適配器

npm install astro-wordpress

(下方使用的 passthroughImageService 隨 Astro 核心一同提供 — 不需額外套件。)

2. 設定 astro.config.mjs

裸機 WP(Astro 和 WP 在同一台主機上,無容器邊界):

// @ts-check
import { defineConfig, fontProviders, passthroughImageService } from "astro/config";
import wordpress from "astro-wordpress";

export default defineConfig({
  server: {
    host: "127.0.0.1",
  },
  adapter: wordpress({
    devProxyTarget: "http://localhost:7001", // 你的本機 WP URL
    outDir: "./wp/wp-content/themes/<theme-name>", // 建置的主題會放在這裡
  }),
  image: {
    service: passthroughImageService(), // 必要 — WP 自行提供/最佳化圖片
  },
});

Docker Compose WP(使用上述 compose.yaml)需要額外三個選項 — 每個都經實際測試,不設定就會失敗(請參閱注意事項):

export default defineConfig({
  server: {
    host: "0.0.0.0", // 綁定所有介面,讓容器可以連入
    allowedHosts: ["host.docker.internal"],
  },
  adapter: wordpress({
    devProxyTarget: "http://localhost:8088",
    outDir: "./wp/wp-content/themes/<theme-name>",
    // WP 容器自身看到的 bind-mounted public/ 目錄路徑 —
    // 不是主機路徑(請參閱注意事項)
    publicDirPath: "/var/www/html/public",
    // 讓執行在容器內部的 PHP 開發模板樁能夠
    // 連回主機上執行的 Astro 開發伺服器
    devServerTarget: "http://host.docker.internal:4321",
  }),
  image: { service: passthroughImageService() },
});

devProxyTarget 必須與 WordPress 實際監聽的位置相符。outDir 是 npm run build 寫入完成的主題的位置;它不需要位於 Astro 專案內。如果它位於專案內(例如在 ./wp/ 下的本機 WP checkout),請將該目錄加入 .gitignore — WordPress 核心及其上傳檔案不屬於 Astro 專案的儲存庫。

3. 加入主題樣式表

WordPress 只有在主題目錄中包含帶有以下標頭的 style.css 時才會識別該主題 — 建立 public/style.css(適配器會自動將其符號連結/複製到 outDir):

/*!
Theme Name: <Theme Name>
Version: 0.0.1
*/

4. 將頁面轉換為 .php.astro

將你想要由 WordPress 提供的每個 src/pages/*.astro 路由重新命名為 src/pages/*.php.astro — 檔案的預設匯出仍會透過 Astro/你現有的佈局和元件進行渲染,無需更改;只有副檔名和最終的輸出格式會改變(index.astro → index.php)。頁面要能正確建置和提供,不需要其他程式碼變更。

非索引的 WP 模板檔案遵循相同的模式:page-template- 前綴會被自動偵測,並轉換為 WordPress 識別的 /* Template Name: ... */ 註解,用於自訂頁面模板,例如 src/pages/page-template-landing.php.astro → 一個可選擇的「Landing」模板。(記錄在適配器的 README 中;本準則未實際使用。)

對於那些必須輸出原始 PHP 且不包含 Surrounding HTML 文件的檔案(例如用於註冊鉤子/欄位的 functions.php.astro — 請參閱 astro-wordpress-acf 技能),請在前言中加入 export const partial = true;。若不加入,Astro 會自動在輸出前綴加上 <!DOCTYPE html>,從而破壞 PHP 檔案。

5. 啟用主題

通用方法:WP 管理後台 → 外觀 → 主題 → 啟用。使用 wp-cli(本機或容器化,請參閱步驟 0):

npm run build
wp theme activate <theme-name> --path=<wp-dir>

驗證

# 1. 開發伺服器和 WP 都啟動了?每個請求都會代理到 devProxyTarget,
#    因此如果 WP 無法連線,即使是靜態資源也會回傳 502
npm run dev &
curl -o /dev/null -s -w "%{http_code}\n" http://127.0.0.1:4321/

# 2. 繞過 WP 代理,直接從開發伺服器查看原始的 Astro 渲染的 PHP 風格輸出
#    — 有助於隔離「這是 Astro 的問題還是 WordPress 的問題」
curl -s -H "by-pass-proxy: 1" http://127.0.0.1:4321/index.php | head -c 300

# 3. 正式環境建置會將真正的純 PHP 檔案放入 outDir
npm run build
grep -c '<?php' wp/wp-content/themes/<theme-name>/index.php

# 4. 主題已啟用 — 透過 wp-cli,或者如果 wp-cli 不可用,直接載入首頁並檢查是否有主題特定的標記
wp theme list --path=<wp-dir> | grep <theme-name>

還沒有本機 WP 安裝可以測試,想以無頭方式(無 wp-cli,無瀏覽器)確認 WP 安裝本身能正常工作?安裝精靈只是一個純文字的表單 POST — 這正是此技能驗證全新 WP 安裝的方式:

curl "http://localhost:8088/wp-admin/install.php?step=2" \
  --data-urlencode "weblog_title=My Site" \
  --data-urlencode "user_name=admin" \
  --data-urlencode "admin_password=<password>" \
  --data-urlencode "admin_password2=<password>" \
  --data-urlencode "pw_weak=1" \
  --data-urlencode "[email protected]" \
  --data-urlencode "Submit=Install WordPress"
# 然後以相同方式登入(使用 cookie jar)以進行後續的管理畫面檢查:
curl -c cookies.txt \
  --data-urlencode "log=admin" --data-urlencode "pwd=<password>" \
  --data-urlencode "wp-submit=Log In" \
  --data-urlencode "redirect_to=http://localhost:8088/wp-admin/" \
  --data-urlencode "testcookie=1" \
  "http://localhost:8088/wp-login.php"
curl -b cookies.txt "http://localhost:8088/wp-admin/" | grep -o "<title>[^<]*</title>"

注意事項

  • 每個開發模式的請求都會代理到 devProxyTarget,而不僅僅是 .php 頁面 — /src、/@、/node_modules,以及任何帶有 by-pass-proxy 標頭的請求是唯一的例外。如果 WordPress 沒有執行,整個網站(包括 public/ 下的圖片/字型)都會回傳 502。在除錯 Astro 端之前,請先檢查 WP 是否確實已啟動。
  • Astro 7 的開發伺服器是一個持續的背景精靈。 第二次執行 npm run dev 不會重新綁定或報錯 — 它只會回報已正在執行的實例(可直接使用 npx astro dev status / stop / logs 來管理)。
  • export const partial = true; — 請參閱步驟 4。這是整個適配器中最不明顯的需求;其失敗模式(PHP 檔案頂部出現多餘的 <!DOCTYPE html>)看起來與 Astro 完全無關。
  • publicDirPath 必須是 WP 容器所見的路徑,而不是主機路徑。 適配器會使用你給定的 publicDirPath 將每個 public/ 檔案符號連結到主題目錄。使用 Docker 時,請給予容器路徑(/var/www/html/public)— 透過雙向檢查結果符號連結來確認:readlink wp-content/themes/<theme>/style.css → /var/www/html/public/style.css,這個路徑在 docker exec <container> cat wp-content/themes/<theme>/style.css 中可以正常解析,但在主機 shell 中會顯示 No such file or directory。如果你省略 publicDirPath,適配器會回退到主機路徑,這在容器內是無效的。
  • astro dev 的精靈鎖定是針對每個專案目錄,而不是每個設定/埠口。 在相同目錄中,當一個普通的 astro dev 已在執行時執行 astro dev --config other.config.mjs --port 4325,只會回報「Dev server already running」在原始埠口上 — 它並不會啟動第二個實例。如果你需要在同一個專案中切換設定(例如裸機 vs. Docker),請先使用 astro dev stop 停止現有的實例。
  • 此轉換本身不會將 wp_head()/wp_footer() 加入佈局,因此外掛注入的 <script>/<style> 標籤、SEO 外掛的 meta 標籤等不會出現。astro-wordpress README 顯示了在佈局中加入 <Fragment set:html={} /> / <?php wp_footer(); ?> 的方法。如果佈局獨立建構自己的 <head>(在移植現有靜態模板時很常見),請將連線這些視為刻意進行的後續步驟,而不是此技能的步驟已經提供的功能。
  • astro check(npm run build 的一部分)可能會因記憶體不足而崩潰,當嘗試對容器啟動後落在 ./wp 中的 WordPress 核心檔案(wp-includes/js/dist/ 等目錄下成千上萬個 .js/.php 檔案)進行型別檢查時。在 Docker WP 已啟動的情況下執行建置之前,請先將 "exclude": ["dist", "wp"] 加入 tsconfig.json — 否則失敗訊息看起來像是無關的 Node 堆積崩潰,與 WordPress 適配器沒有明顯關聯。
  • Biome(或任何在整個儲存庫上執行的 linter/formatter)也會嘗試處理 ./wp,一旦它存在,原因相同 — 在執行專案的 lint/format 命令之前,請加入忽略項目(例如在 biome.json 中加入 "files": { "ignore": ["wp/**"] })。
  • 動態 rest-param 路由無法轉換。 src/pages/blog/[...slug].astro(或任何 [...x].astro)無法變成 [...x].php.astro — Astro 的路由器會直接拒絕它(「rest parameter must be a standalone segment」),因為 .php 後綴破壞了區段邊界。將這些路由保留為純 .astro 並排除在 WP 主題之外,除非內容本身正在遷移到 WP。

下一步

一旦適配器連接好:

  • astro-wordpress-acf — 透過 ACF 使頁面的特定區段可從 WP 後台編輯。
  • astro-wordpress-menus — 將頁首/頁尾/導覽元件連接到 WordPress 管理的選單(外觀 → 選單),而不是使用硬編碼的連結。
  • astro-wordpress-global-settings — 為不局限於任何單一頁面的值加入全站范围的「主題選項」頁面(需要 ACF Pro 或 Secure Custom Fields)。

相關技能