前几天完成了一次 WordPress 博客到 Astro 静态博客的迁移。背景是博客更新没这么频繁,而且很多动态能力不需要了,开了评论,结果后台几百个各类广告的评论没有任何意义了。博客内容本身不多,就是特别要注意旧链接和旧资源要依然可靠地工作,不然SEO就全清空了。
这篇文章记录迁移过程中的关键判断、实现方式和一些容易被忽略的细节。新站以 Astro 7 和 Tailwind CSS 4 为基础;使用了 Codex + GPT-5.6-terra 作为协作工具。
迁移目标:不是重做网站,而是保住内容资产
从动态博客迁移到静态博客,最容易产生的误解是:导出文章、换一个主题、部署完成,就算迁移成功。
实际上,内容站迁移至少要同时满足几件事:
- 已发布文章能够继续访问;
- 历史链接尽量不变,尤其是来自搜索引擎、社交平台和其他文章的链接;
- 图片、表格、引用和代码等正文内容不出现明显损坏;
- 新站的维护方式比旧站更简单,特别是静态站点,生成托管就结束了;
- 视觉风格可以更新,但不应以牺牲阅读体验为代价。
因此,这次迁移的目标并不是复刻旧主题,也不是把 WordPress 的全部功能搬到静态站,而是建立一个内容优先、生成结果稳定、后续维护成本更低的博客。
第一步:先审计导出数据,再决定迁移范围
先从 WordPress 的后台,tools > export 导出全部数据的 xml 。
然后再把 wp-content 文件夹原封不动的复制到 astro 的 public 文件夹下。
WordPress 导出文件看起来像是一份内容备份,但它实际混合了多种记录:文章、页面、附件、草稿、评论、导航数据,以及主题或插件写入的元信息。
如果不先分类,后面很容易把无用数据也带进新站,或者漏掉真正需要保留的内容。我的处理方式是先回答四个问题:
- 哪些是已经公开发布的文章?
- 哪些页面仍然需要保留访问入口?
- 正文引用了哪些上传资源,它们是否已在本地保存?
- 哪些内容不适合、也没有必要迁移?
最终,迁移范围被限定为已发布文章和一个必要的兼容页面。评论、评论元数据、WordPress 后台、附件详情页、搜索、订阅源、主题模板记录和未发布草稿均不迁移。
这个“先决定不迁移什么”的步骤很重要。静态站不应机械复制动态系统,而应只保留真正有价值、可长期维护的部分。
第二步:把历史 URL 当作迁移契约
内容迁移中最有价值的资产,除了文章本身,就是既有 URL。
旧文章使用的是按日期组织的永久链接:
1 | /YYYY/MM/post-slug/ |
但是如果是使用query string也就是 ?slug=xxx 的就很难办了,静态托管不太支持这种形式的链接,好在默认的是用 path 区分的。
新站继续生成完全相同的路径,而不是改成更短的 /post-slug/。后者看似更简洁,却会让已经被收录、转发或收藏的链接全部失效,并把大量本可避免的 404 留给读者和搜索引擎。
在 Astro 中,这种路径可以通过动态页面路由实现。文章元数据中保留发布日期和 slug,在构建阶段生成对应的年、月、slug 参数;最终输出仍是静态 HTML,却能稳定覆盖每一篇历史文章。
路径:
1 | src\pages\[year]\[month]\[slug].astro |
获取静态路径的函数:
1 | export async function getStaticPaths() { |
这里还有两个细节:
- 输出形式要兼容结尾斜杠;部署平台、静态站生成设置和站内链接应保持一致。
?p=123这类旧式查询参数链接不能由纯静态页面天然接住,是否保留要看部署平台是否支持重定向规则。它的优先级通常低于公开文章的永久链接,但上线前仍应单独审计。
页面可以改版,URL 尽量不要改。
第三步:从 Gutenberg HTML 到可维护的 Markdown
WordPress 的正文常常来自 Gutenberg 编辑器。导出后的内容虽然是 HTML,但里面往往夹杂区块注释、展示性类名、内联样式和编辑器遗留结构。
迁移时的原则是保留语义,而不是保留原始标签结构。
需要保留的通常包括:
- 标题、段落和强调;
- 超链接与图片;
- 有序或无序列表;
- 引用块、代码块;
- 对比表格等承载信息的结构。
而 WordPress 区块注释、纯展示用途的 class、编辑器生成的空容器,以及主题相关的样式说明,都应该去掉。它们在新站没有意义,反而会让 Markdown 难读、难维护。
尤其要留意表格。普通段落转 Markdown 通常比较顺利,但表格、嵌入内容和含有转义 CSS 的文章很容易出现格式残留。与其追求一次自动转换全部正确,不如先完成批量转换,再进行针对性人工复查。重点检查:
- 表格的列数和表头是否正确;
- 代码块是否被错误拆分;
- 图片链接是否仍然有效;
- HTML 实体和转义字符是否污染正文;
- 长文章的标题层级是否合理。
迁移完成后,清理过的 Markdown 应当成为仓库里的正式内容源。一次性的导入脚本可以不保留;真正重要的是让以后编辑文章时,不必重新理解旧 CMS 的导出格式。
第四步:图片不急着“优化”,先确保不丢
图片往往是迁移中最容易被低估的部分。文章正文能渲染,不代表资源一定齐全;一旦原站下线或上传目录路径发生变化,历史文章中的图片就会全部变成断链。
这次采用的策略很朴素:保留原有上传目录结构,将文章中的图片路径继续指向本地静态资源。例如:
1 | /wp-content/uploads/2024/01/example-image.png |
只要同样的文件存在于静态站的 public/wp-content/uploads 下,构建后的访问路径就能保持不变。
这有几个好处:
- 不需要逐篇修改图片 URL;
- 不会因为文件改名导致旧内容失效;
- 可以先完成可靠迁移,再选择性做 WebP、压缩、尺寸优化或图片组件改造;
- 导入流程不会移动、重命名或修改原始资源,降低误操作风险。
迁移时建议把“文章中引用到的唯一图片 URL”与本地资源目录做一次逐项比对。构建成功只说明代码没有报错,不代表每一张图片都存在。
第五步:用内容集合约束文章元数据
Astro 的内容集合适合承接 Markdown 博客。相比把文章文件当作完全自由的文本,它可以为 Front Matter 建立 Schema,让标题、日期、slug、摘要、标签等字段在构建时得到校验。
例如,一篇文章至少应有标题和发布日期,实际使用的定义如下:
1 | import { defineCollection } from "astro:content"; |
对应的 md 的frontmatter:
1 | --- |
这种看似简单的约束,能尽早发现日期格式错误、漏填标题、标签结构不一致等问题。对于需要按年月生成路由、按日期排序、生成首页归档和 sitemap 的静态博客来说,内容元数据就是整个站点的基础数据层。
第六步:视觉重做应服务于阅读
迁移是重新设计信息层级的机会,但不是给页面堆更多装饰的理由。
新站采用了克制的单色编辑式视觉:浅色背景、深色文字、细规则、明确的排版层级,以及较少的元信息干扰。首页以归档和文章索引为主,文章页则让正文占据视觉中心。
Tailwind CSS 4 很适合这类工作。它把颜色、间距、断点和排版规则集中在一套可组合的样式体系中,既能快速完成页面,也便于后续逐渐收敛为稳定的设计令牌。
如果要加入粒子、网格等氛围装饰,也应遵守几个边界:
- 仅作为背景,不阻塞阅读或点击;
- 密度和对比度保持很低;
- 不要在所有页面重复出现;
- 对
prefers-reduced-motion提供静态效果或直接关闭动效。
好的博客视觉通常不会抢走文章的注意力,而是在读者没有察觉时让阅读更顺畅。
第七步:不要遗漏分页、404 和兼容页面
静态站常见的遗漏不在文章详情页,而在边缘页面。
首页需要稳定的排序和分页策略。如果旧站已经存在 /page/2/ 一类的访问入口,最好一起生成对应的静态兼容页面。即使首页的文章数量不多,也应考虑它未来增长后的行为,而不是只为当前数据量设计。
同样需要补齐的还有:
- 404 页面;
- 旧占位页面的替代内容;
- 站内导航和页脚链接;
- canonical URL;
- sitemap;
- 部署平台支持的重定向配置。
这些页面和配置平时不显眼,却直接决定迁移后的完整度,也影响搜索引擎对新站结构的理解。
Codex + GPT-5.6-terra 在这次迁移中做了什么
这次没有把 AI 当成“点一下就自动完成迁移”的工具,而是把 Codex + GPT-5.6-terra 放在适合它的位置:处理重复劳动、协助建立检查框架,以及加快局部实现。
它尤其适合协助完成以下工作:
- 阅读导出说明并整理迁移范围;
- 归纳内容字段、路由规则和资产清单;
- 生成 Astro 内容集合、动态路由和分页的初始实现;
- 对 HTML 转 Markdown 后的残留内容进行模式识别;
- 编写构建前检查清单和人工验收项;
- 在已有设计方向下协助搭建组件和 Tailwind 样式。
但有几件事仍然必须人工确认:
- 每一篇公开文章是否对应正确的历史 URL;
- 图片和表格是否在语义与视觉上都正确;
- 是否错误迁入草稿、评论或敏感元数据;
- 站点文案和视觉是否符合预期;
- 生产构建、部署规则和真实访问结果是否一致。
AI 很擅长把模糊任务拆成可执行步骤,也很擅长处理大量重复格式;但迁移的最终责任仍在于人对内容、兼容性和发布结果的验收。
上线前检查清单
最后,给这类迁移留一份简单但实用的检查清单:
- 所有已发布文章均已迁入,草稿没有被发布;
- 历史文章 URL 的年、月、slug 和结尾斜杠符合旧链接;
- 文章内图片、链接、表格、代码块和引用显示正常;
- 首页排序、分页和兼容分页路径正常;
- 404 与必要兼容页面已经提供;
- canonical、sitemap 和基础 SEO 信息已配置;
- 生产构建通过;
- 在部署后的真实域名环境中抽查访问与资源加载;
- 根据托管平台能力,为低优先级旧链接补充重定向。
总结
这次迁移最重要的收获是:静态化不只是换一个框架,而是一次重新梳理内容边界和长期维护方式的机会。
保住 URL,保住内容语义,保住资源路径;把不再需要的动态功能留在过去;再用一套足够轻、足够明确的内容模型和页面结构承接未来更新。