从 WordPress 迁移

本页内容

使用 EmDash 管理后台分析 WordPress 站点、准备兼容的集合、导入内容、复制媒体并重写 URL。在导入后的站点通过验证之前,请保持 WordPress 站点可用。

开始之前

请准备以下内容:

  • WordPress 数据库和 wp-content/uploads 的备份。
  • 一个已配置存储的 EmDash 站点(如果你打算复制媒体)。
  • 一个 EmDash 管理员账户。WordPress 导入需要 import:execute 权限。
  • 一份完整的 WordPress eXtended RSS(WXR)导出文件,或者在 WordPress 站点上安装 EmDash Exporter 插件。

请记录当前的固定链接结构、规范来源(canonical origin)、重定向、菜单、启用的文章类型、分类法,以及新站点必须保留的所有由插件拥有的字段。

选择导入方法

方法适用场景包含的数据
WXR 上传你可以从 Tools → Export 导出导出文件中包含的数据,包括文章、页面、自定义文章类型、分类法术语、可复用区块、作者和附件 URL
EmDash Exporter你控制该 WordPress 站点,并且可以安装 exporter需认证才能获取的内容,以及受支持的评论、菜单、站点设置、SEO 字段、分类法和媒体元数据

在没有 exporter 的情况下输入站点 URL,只会探测公开的 WordPress REST API。该探测可以检测到 WordPress,并统计公开的文章、页面和媒体数量,但无法执行直接的 REST 导入。

导出 WXR 文件

在 WordPress 中打开 Tools → Export,选择 All content,然后下载 XML 导出文件。WXR 文件指向 WordPress 来源上的媒体;它不包含附件的字节内容。

连接 EmDash Exporter

在 WordPress 中打开 Tools → EmDash Migration 并生成迁移密钥。把密钥粘贴到 EmDash 导入页面中。

你也可以输入 WordPress 站点 URL。检测到 exporter 后,通过 WordPress 应用密码界面授权 EmDash。在本地 HTTP 开发站点上,由于授权回调需要 HTTPS,请手动输入 WordPress 用户名和应用密码。

通过管理后台导入

  1. 在 EmDash 侧边栏中打开 Import WordPress,或访问 /_emdash/admin/import/wordpress。

  2. 上传 WXR 文件、粘贴 exporter 迁移密钥,或输入 WordPress URL。

  3. 查看分析结果。对每种 WordPress 文章类型,确认目标集合、必填字段,以及与现有字段的兼容性。

  4. 将 WordPress 作者映射到 EmDash 用户。未映射的源作者可以用访客 byline 表示,因此展示署名不依赖于授予 EmDash 登录权限。

  5. 对于 exporter 导入,选择是否导入菜单、站点标题和标语、logo 和 favicon,以及受支持的 SEO 值。这些开关不属于 WXR 路径。

  6. 开始导入。EmDash 会在创建条目之前,先创建缺失的兼容集合和字段。

  7. 如果发现了附件,请运行媒体步骤。EmDash 会下载源字节内容,通过已配置的存储适配器存储它们,并重写匹配的内容 URL。

转换行为

状态

导入器按如下方式映射 WordPress 状态:

WordPressEmDash
publishpublished
draftdraft
pendingdraft
privatedraft
future、trash 或未知状态draft

计划发布的日期和 WordPress 的可见性规则不会根据这些状态重建。发布之前请检查每一篇导入的草稿。

富文本和可复用区块

Gutenberg 标记会被转换为 Portable Text。经典 HTML 由同一个转换器处理。请在渲染后的 EmDash 站点中检查复杂区块、嵌入内容、短代码、页面构建器标记和插件定义的区块。

WXR 中的 wp_block 条目会作为 sections 导入。它们不会被导入到普通的内容集合中。

集合和字段

默认的文章类型映射包括 post 到 posts,以及 page 到 pages。自定义文章类型使用经过清理的集合 slug。准备步骤会添加分析所需的标准标题、Portable Text 内容、摘要和特色图片字段。

类型兼容的现有字段会被复用。类型不匹配会阻止该集合的映射;导入器不会把现有字段强制转换为其他类型。

自定义字段和 SEO 数据

WXR 分析会报告非内部的 post-meta 键,并建议字段名称和类型,但 WXR 数据库导入写入的是标准的导入字段,而不是复制每一个任意的 meta 键。请把分析结果当作清单,其中列出的字段可能需要单独转换。

当目标集合有匹配的字段时,EmDash Exporter 路径可以复制自定义 meta 和 Advanced Custom Fields(ACF)的值。启用相应的导入开关后,它还可以创建并填充受支持的特色图片字段以及 Yoast 或 Rank Math 的 SEO 字段。请检查序列化的 PHP 值、重复器、灵活内容和插件特有的结构,而不要假定它们在 WordPress 中的表示与 EmDash 字段类型相匹配。

作者和 byline

被映射的 WordPress 作者会成为条目所有者。展示署名使用 byline。如果不存在用户映射,EmDash 会根据 WordPress 作者身份创建或复用访客 byline。

分类法

分类和标签会被导入到匹配的 EmDash 分类法定义中。exporter 路径可以为自定义分类法创建定义。没有匹配 EmDash 定义的 WXR 自定义分类法会被报告为缺失,其指派会被跳过。

媒体

媒体去重比较的是已下载字节内容的 SHA-1 哈希。具有相同哈希的现有媒体行会被复用。文件名和 WordPress ID 不是去重的键。

在 EmDash 下载附件期间,源站点必须保持可访问。来自附件 URL 的重定向在被跟随之前会先经过验证。

重试部分完成的导入

管理后台导入被设计为会跳过已有条目,但其匹配边界很重要:

  • 现有内容按集合、slug 和语言区域匹配,而不是按 WordPress ID 匹配。
  • 如果两次尝试之间源 slug 发生了变化,请检查两个条目并手动解决重复问题。
  • 重新运行媒体步骤时,会按内容哈希复用已存储的字节相同的文件。
  • exporter 流程发送有界的数据块。重新启动浏览器流程会重新运行内容页面,并根据被跳过的条目重建关系映射。

管理后台不会持久化 WXR 恢复文件。emdash import wordpress 上的 --resume 标志属于另一个 CLI 工作流,该工作流会把转换后的 JSON 文件写入磁盘;它不会恢复管理后台的数据库导入。

切换上线前的验证

对照源站点检查导入后的站点:

  • 按文章类型和状态统计条目数量。
  • 打开具有代表性的 Gutenberg、经典编辑器、短代码和页面构建器内容。
  • 确认特色图片和内嵌媒体能从 EmDash URL 解析。
  • 检查作者、byline、分类、标签、自定义分类法和翻译。
  • 如果通过 exporter 导入,请测试菜单、评论、站点身份和 SEO 字段。
  • 抓取旧的公开 URL,并为每一个发生变化的路由准备重定向。
  • 验证草稿对未登录的访客仍然不可访问。

在新站点已在生产环境中成功运行、且不再需要回滚之前,请保留备份和 WordPress 部署。

故障排除

无法解析 XML 文件

请从 Tools → Export 重新导出文件,并确认下载已完成。不要用会改变编码的工具编辑 XML。

集合被标记为不兼容

现有字段的 slug 相同,但类型不同。请在重试之前更改文章类型的映射,或在 Content Types 下调和该字段。准备步骤会添加缺失的字段,但不会更改现有字段的类型。

媒体 URL 下载失败

请检查源附件是否无需 WordPress 会话即可访问。需要认证才能访问的媒体、已删除的文件,以及指向私有网络地址的重定向都会单独失败,并保留在媒体错误列表中。

适配主题

归档路由使用 getEmDashCollection(),slug 路由使用 getEmDashEntry()。entry.id 是路由标识符,通常就是 slug;entry.data.id 是关系辅助函数使用的已存储内容 ID。

下面的路由会渲染一篇导入的文章:

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

const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.rewrite("/404");

const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) return new Response("Could not load the post", { status: 500 });
if (!post) return Astro.rewrite("/404");
---

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

路由和组件的映射请阅读移植 WordPress 主题。端点契约和确切的重试边界请阅读内容导入。