如果真要把 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,语言不重要。流程大概是:
- 读 XML。
- 过滤
wp:post_type为post和page的内容。 - 取
title、pubDate、wp:post_date、category、content:encoded。 - 生成 frontmatter。
- 把正文写到
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_url、alt_text、caption、post。再从正文里扫 <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 的结构跑稳。页面难看几天没事,旧链接断几天就不太好了。
参考: