給 WordPress 開發者的 EmDash

本頁內容

EmDash 把熟悉的 WordPress 概念——文章、頁面、分類法、選單、小工具與媒體庫——帶進現代化的 Astro 技術堆疊。你的內容管理知識可以直接沿用。

依然熟悉的部分

你在 WordPress 裡熟悉的概念,在 EmDash 中都是第一級功能:

  • Collections 就像 Custom Post Types——定義內容結構,在範本中查詢
  • Taxonomies 同理——階層式(如分類)與扁平式(如標籤)
  • Menus 支援拖曳排序與巢狀項目
  • Widget Areas 用於側欄與動態內容區域
  • Media library 含上傳、整理與圖片管理
  • 編輯不必碰程式碼就能使用的 Admin UI

不同之處

實作會變,但心智模型不變:

以 TypeScript 取代 PHP

範本是 Astro 元件。語法更乾淨,概念相同:在伺服器上執行、輸出 HTML 的程式碼。

以 Content API 取代 WP_Query

getEmDashCollection() 這類查詢函式取代 WP_Query。沒有 SQL,只有函式呼叫。

以檔案為基礎的路由

src/pages/ 裡的檔案就是 URL。不必背重寫規則或範本階層。

以元件取代範本片段

import 並使用元件。與 get_template_part() 同一個想法,組織更清楚。

速查表

WordPressEmDash說明
Custom Post TypesCollections透過管理後台或 API 定義
WP_QuerygetEmDashCollection()篩選、筆數、分類法查詢
get_post()getEmDashEntry()回傳項目或 null
Categories/TagsTaxonomies階層支援維持不變
register_nav_menus()getMenu()第一級選單支援
register_sidebar()getWidgetArea()第一級小工具區域
bloginfo('name')getSiteSetting("title")網站設定 API
the_content()<PortableText />結構化內容呈現
ShortcodesPortable Text blocks自訂元件
add_action/filter()Plugin hooks例如 content:beforeSave
wp_optionsctx.kv鍵值儲存
Theme directorysrc/ directory元件、版面、頁面
functions.phpastro.config.mjs + EmDash config建置與執行階段設定

Content API

查詢 Collections

WordPress 使用 WP_Query 或輔助函式查詢。EmDash 使用具型別的查詢函式。

WordPress

<?php
$posts = new WP_Query([
  'post_type' => 'post',
  'posts_per_page' => 10,
  'post_status' => 'publish',
  'category_name' => 'news',
]);

while ($posts->have_posts()) :
$posts->the_post();
?>

  <h2><?php the_title(); ?></h2>
  <?php the_excerpt(); ?>
<?php endwhile; ?>

EmDash

---
import { getEmDashCollection } from "emdash";

const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
limit: 10,
where: { category: "news" },
});

---

{posts.map((post) => (

  <article>
    <h2>{post.data.title}</h2>
    <p>{post.data.excerpt}</p>
  </article>
))}

取得單一項目

WordPress

<?php
$post = get_post($id);
?>
<article>
  <h1><?php echo $post->post_title; ?></h1>
  <?php echo apply_filters('the_content', $post->post_content); ?>
</article>

EmDash

---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";

const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);

## if (!post) return Astro.redirect("/404");

<article>
  <h1>{post.data.title}</h1>
  <PortableText value={post.data.content} />
</article>

範本階層

WordPress 用範本階層決定由哪個檔案呈現頁面。Astro 使用明確的以檔案為基礎的路由。

WordPress TemplateEmDash 對應
index.phpsrc/pages/index.astro
single.phpsrc/pages/posts/[slug].astro
single-{type}.phpsrc/pages/{type}/[slug].astro
page.phpsrc/pages/pages/[slug].astro
archive.phpsrc/pages/posts/index.astro
archive-{type}.phpsrc/pages/{type}/index.astro
category.phpsrc/pages/categories/[slug].astro
tag.phpsrc/pages/tags/[slug].astro
search.phpsrc/pages/search.astro
404.phpsrc/pages/404.astro
header.php / footer.phpsrc/layouts/Base.astro
sidebar.phpsrc/components/Sidebar.astro

範本片段 → 元件

WordPress 的範本片段會變成 Astro 元件:

WordPress

// In template:
get_template_part('template-parts/content', 'post');

// template-parts/content-post.php:

<article class="post">
  <h2><?php the_title(); ?></h2>
  <?php the_excerpt(); ?>
</article>

EmDash

---
const { post } = Astro.props;
---

<article class="post">
	<h2>{post.data.title}</h2>
	<p>{post.data.excerpt}</p>
</article>
---
import PostCard from "../components/PostCard.astro";
import { getEmDashCollection } from "emdash";

const { entries: posts } = await getEmDashCollection("posts");
---

{posts.map((post) => <PostCard {post} />)}

選單

EmDash 提供第一級選單支援,並會自動解析 URL:

WordPress

<?php
wp_nav_menu([
  'theme_location' => 'primary',
  'container' => 'nav',
]);
?>

EmDash

---
import { getMenu } from "emdash";

## const menu = await getMenu("primary");

<nav>
  <ul>
    {menu?.items.map((item) => (
      <li>
        <a href={item.url}>{item.label}</a>
      </li>
    ))}
  </ul>
</nav>

選單可透過管理後台、種子檔或 WordPress 匯入建立。

小工具區域

小工具區域與 WordPress 的側欄類似:

WordPress

<?php if (is_active_sidebar('sidebar-1')) : ?>
  <aside>
    <?php dynamic_sidebar('sidebar-1'); ?>
  </aside>
<?php endif; ?>

EmDash

---
import { getWidgetArea } from "emdash";
import { PortableText } from "emdash/ui";

## const sidebar = await getWidgetArea("sidebar");

{sidebar && (

  <aside>
    {sidebar.widgets.map((widget) => {
      if (widget.type === "content") {
        return <PortableText value={widget.content} />;
      }
      // Handle other widget types
    })}
  </aside>
)}

網站設定

網站選項與自訂器設定對應到 getSiteSetting()

WordPressEmDash
bloginfo('name')getSiteSetting("title")
bloginfo('description')getSiteSetting("tagline")
get_custom_logo()getSiteSetting("logo")
get_option('date_format')getSiteSetting("dateFormat")
home_url()Astro.site
import { getSiteSetting } from "emdash";

const title = await getSiteSetting("title");
const logo = await getSiteSetting("logo"); // Returns { mediaId, alt, url }

分類法

概念相同——階層式(如分類)或扁平式(如標籤):

import { getTaxonomyTerms, getEntryTerms, getTerm } from "emdash";

// Get all categories
const categories = await getTaxonomyTerms("categories");

// Get a specific term
const news = await getTerm("categories", "news");

// Get terms for a post
const postCategories = await getEntryTerms("posts", postId, "categories");

Hooks → 外掛系統

WordPress 的掛勾(add_actionadd_filter)對應 EmDash 的外掛掛勾:

WordPress HookEmDash Hook用途
save_postcontent:beforeSave儲存前修改內容
the_contentPortableText components轉換已呈現的內容
pre_get_postsQuery options篩選查詢
wp_headLayout <head>在 head 加入內容
wp_footerLayout before </body>在頁尾加入內容

EmDash 的優勢

型別安全

全面使用 TypeScript。Collections、查詢與元件皆有完整型別,不必再猜欄位名稱或回傳型別。

效能

沒有 PHP 負擔。預設靜態產生,需要時伺服器端呈現,並可部署到邊緣。

現代開發體驗

Hot module replacement。元件化架構。Vite、TypeScript、ESLint 等現代工具鏈。

以 Git 為主的部署

程式碼與範本在 git,內容在資料庫。不必 FTP、不必糾結檔案權限,也較少整站被駭的風險。

預覽連結

EmDash 會產生帶 HMAC 簽章權杖的安全預覽 URL。編輯不必登入正式環境就能預覽草稿——分享連結即可,不必給帳密。

沒有外掛衝突

WordPress 常見的外掛衝突在 EmDash 中消失。外掛在隔離的環境中以明確的 API 執行,不會污染全域狀態。

內容編輯體驗

編輯使用類似 wp-admin 的 EmDash 管理後台:

  • 含最近活動的 Dashboard
  • 支援搜尋、篩選與批次動作的 Collection 清單
  • 內容用的富文字編輯器(Portable Text,不是 Gutenberg)
  • 支援拖放上傳的媒體庫
  • 支援拖曳排序的選單建構器
  • 側欄內容用的小工具區域編輯器

編輯體驗熟悉,底層技術已現代化。

遷移路徑

EmDash 可直接匯入 WordPress 內容:

  1. 從 WordPress 匯出(工具 → 匯出)
  2. 在 EmDash 管理後台上傳 .xml
  3. 將文章類型對應到 collections
  4. 匯入內容與媒體

文章、頁面、分類法、選單與媒體都會轉移。Gutenberg 區塊會轉成 Portable Text。自訂欄位會被分析並對應。

完整步驟見 WordPress 遷移指南

下一步