4 分钟阅读

WordPress 导出到 Astro,我会按这个清单慢慢搬

从 WordPress 迁到 Astro,真正麻烦的不是新站搭起来,而是文章、图片、评论、短代码、旧链接这些细节别丢。

如果真要把 WordPress 文章搬到 Astro,我不会先打开主题,也不会先调样式。我会先把内容备份下来。

迁移博客最怕的不是页面丑。丑可以慢慢改。最怕的是旧文章丢字段、图片丢路径、URL 断一片,最后也不知道哪里开始错的。

下面这份清单更像我会给自己留的操作顺序。

1. 先导出 WordPress 内容

后台导出:

Tools -> Export -> All content -> Download Export File

会拿到一个 XML,也就是 WXR。里面通常有文章、页面、评论、自定义字段、分类、标签、自定义类型、用户这些信息。

如果能 SSH 到服务器,我更喜欢用 WP-CLI:

wp export --dir=./exports --post_type=post,page --post_status=publish

文章很多时可以按年份拆:

wp export --dir=./exports --post_type=post --start_date=2018-01-01 --end_date=2018-12-31

注意一个坑:WXR 会记录 attachment,但不等于图片文件已经在本地了。图片还是要单独下载。

2. 把旧 URL 表先弄出来

迁移前先做一张表:

old_url,title,date,post_id,slug
https://example.com/2019/hello-world/,Hello world,2019-01-01,123,hello-world

如果 WordPress 原来 permalink 是 /%year%/%monthnum%/%postname%/,Astro 就尽量继续生成这个路径。不要为了“看起来更清爽”把所有 URL 改掉。

我现在做旧站恢复,宁愿 frontmatter 多写一个 path

path: "2019/01/01/hello-world/"
permalink: "https://www.example.com/2019/01/01/hello-world/"

以后生成页面、RSS、sitemap、canonical,都从这里拿。少猜。

3. WXR 转 Markdown

这一步可以写 Node、Python,语言不重要。流程大概是:

  1. 读 XML。
  2. 过滤 wp:post_typepostpage 的内容。
  3. titlepubDatewp:post_datecategorycontent:encoded
  4. 生成 frontmatter。
  5. 把正文写到 src/content/posts/YYYY/MM/DD/slug/index.md

正文处理要保守。WordPress block editor 会留下类似这样的注释:

<!-- wp:paragraph -->
<p>正文</p>
<!-- /wp:paragraph -->

这些注释可以去掉,但不要太激进。第一次迁移我宁愿保留 HTML,也不要把表格、代码块、相册搞坏。Astro 的 Markdown 里放 HTML 是可以的,后面再慢慢清理。

4. 图片单独跑一轮

图片处理我会分两步。

先从 WordPress REST API 的 media endpoint 拿附件列表,记录 source_urlalt_textcaptionpost。再从正文里扫 <img src=""> 和 Markdown 图片链接。两边合起来,才比较不容易漏。

下载后我会放到类似:

public/wp-images/2019/01/hello-world/example.jpg

然后替换正文里的远程地址:

<img src="/wp-images/2019/01/hello-world/example.jpg" alt="...">

图片不要只看下载成功,还要检查引用是否存在。这个步骤很枯燥,但很值。

5. 评论看情况

WordPress 的评论会在 WXR 里。个人博客如果评论不多,我会生成一个静态 JSON,然后在文章末尾展示旧评论。

如果评论很多,或者有垃圾评论,我会先归档,不急着展示。迁移初版先把文章救出来,评论可以第二轮做。

这不是不重视评论,是迁移时要分优先级。文章正文和 URL 是主线。

6. Astro 里建 Content Collections

迁到 Astro 后,别让 Markdown 随便长。

src/content.config.ts 里先把字段定死:

const postsCollection = defineCollection({
  loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/posts' }),
  schema: z.object({
    title: z.string(),
    date: z.coerce.date(),
    excerpt: z.string(),
    path: z.string(),
    permalink: z.string().optional(),
    tags: z.array(z.string()).default([]),
    categories: z.array(z.string()).default([]),
  }),
});

然后跑:

npm run astro -- sync
npm run build

构建报错不是坏事。迁移阶段越早报错越好。

7. SEO 检查不要省

迁移完至少检查这些:

  • 首页 title 和 description。
  • 每篇文章 canonical。
  • RSS 里是否是新域名和旧路径。
  • sitemap 里是否包含文章页。
  • 旧 URL 是否 200 或 301 到新 URL。
  • 404 页是否 noindex
  • 图片是否有明显破图。

Astro 的 sitemap 集成依赖 astro.config.mjs 里的 site。如果这个值没配好,sitemap 和 canonical 很容易跟着错。RSS 也一样,最好生成绝对地址。

8. 最后再改样式

样式最后做。

这句话写给我自己。迁移时最容易被新主题吸走注意力,一会儿改字体,一会儿改卡片,一会儿改暗色模式。结果内容还没核完。

先把 WordPress 的文章搬准,再把 Astro 的结构跑稳。页面难看几天没事,旧链接断几天就不太好了。

参考: