面向 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 hookscontent: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 迁移指南

下一步