Featured image of post WordPress 迁移到 Hugo

WordPress 迁移到 Hugo

最近把博客从 WordPress 迁移到了 Hugo,前前后后折腾了一天,但迁移完成后感觉一身轻松。

为什么要迁移

响应速度慢。WordPress 是个 PHP 动态站,每次访问都要查询数据库、渲染模板。哪怕服务器配置不差,页面首屏也要几百毫秒到一秒。后台编辑器尤其明显——打一个字要等一会才有反应,注意力不断被打断,体验很差。

爬虫攻击多。WordPress 曝光率高,xmlrpc.phpwp-login.php 天天被全球各地的 IP 扫描爆破。服务器日志里这类记录能占 90%,看着心烦,清理也累。

性能开销大。MySQL + PHP + WordPress 主题 + 插件,跑在 2C4G 的小机器上,并发一高就卡。

Hugo 全部是静态文件,CDN 友好,页面毫秒级响应;不用数据库,不用 PHP,攻击面极小;配合 Git 管理,历史版本完整,回滚方便;写完 Markdown 推送到 GitLab,Runner 自动构建部署,全程零人工干预。

一句话总结:WordPress 是瑞士军刀,Hugo 是狙击枪——够用的场景下,越简单越舒服。

迁移要解决的核心问题:旧链接

WordPress 的文章链接是 ?p=123 这种动态格式,Hugo 是 /p/article-slug/ 这种静态格式。如果不做处理,所有搜索引擎收录的老链接都会 404,之前积累的 SEO 权重全部清零。

好在这个问题可以在网关层面解决——我用的是雷池 WAF,它的底层是 Nginx,自定义空间比较大。

第一步:自定义 Nginx 重定向规则

在雷池后台的 Nginx 自定义配置中加入以下三条规则:

雷池 WAF Nginx 自定义配置

1
2
3
4
5
6
7
8
9
if ($wp_article) {
    return 301 https://你的hugo博客地址$wp_article;
}
if ($wp_page) {
    return 301 https://你的hugo博客地址$wp_page;
}
if ($wp_cat) {
    return 301 https://你的hugo博客地址$wp_cat;
}

这三条规则分别处理文章、页面、分类三种旧链接的 301 重定向。

第二步:编写 Nginx map 映射表

规则写好了,但 Nginx 还不知道 wp_articlewp_pagewp_cat 这些变量具体对应哪些新链接。这就需要写三张 map 映射表。

在雷池的 nginx/conf.d/ 目录下新建一个 wp_redirect.conf(文件名任意),内容类似这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 文章映射:WordPress ?p=xxx -> Hugo /p/slug/
map $arg_p $wp_article {
    default "";
    "123" "/p/wordpress-plugin-development-guide/";
    "456" "/p/backup-strategy-for-nas/";
    # ... 所有文章旧链接映射
}

# 页面映射:WordPress ?page_id=xxx -> Hugo /about
map $arg_page_id $wp_page {
    default "";
    "2" "/about/";
    "5" "/links/";
    # ...
}

# 分类映射:WordPress ?cat=xxx -> Hugo /categories/name
map $arg_cat $wp_cat {
    default "";
    "3" "/categories/nas/";
    "7" "/categories/docker/";
    # ...
}

第三步:从 WordPress 导出数据

WordPress 后台 → 工具 → 导出所有内容,会生成一个 .xml 文件,包含了所有文章、页面、分类、标签、评论数据。

WordPress 导出工具

把这个 xml 丢给 AI(DeepSeek 或其他),让它帮你完成两件事:

  1. 生成 Hugo 格式的文章 Markdown 文件:遍历 xml 中的文章节点,按 front matter 格式输出,处理好分类、标签、日期等字段
  2. 生成上面三张 map 映射表的内容:输出 {旧ID}: {新路径} 的格式,直接贴到 wp_redirect.conf

AI 处理 xml 很在行,只要你把 Hugo 的目录结构和链接格式要求说清楚,它基本能一次性生成可用的内容。

进阶迁移:评论数据也搬过来

上面的步骤解决了文章内容的迁移,但如果你的博客接入了 Waline 这类评论系统,原来的评论记录怎么迁移?

Waline 的数据存储在 MySQL 里,评论、文章浏览数、用户信息都在数据库中。把 WordPress 导出的 xml 丢给 AI,让它根据 Waline 的表结构生成 SQL 插入脚本:

  1. 评论表脚本:解析 xml 中的评论节点,生成 INSERT INTO Comment ... 语句
  2. 浏览数脚本:如果 WordPress 有浏览数插件,同步迁移
  3. 用户表脚本:评论者的昵称、邮箱、网站等

生成后执行 SQL,评论就回来了。

另外还有一个细节:文章内容中的内链。WordPress 文章里通常会互相引用,迁移后这些链接如果不处理,跳转到新站也会 404。让 AI 在生成 Markdown 时一并把内链替换成新的 Hugo 格式,这样整站迁移后用户体验才是无缝的。

总结

迁移链路大概是这个样子:

1
2
3
4
5
6
7
8
9
WordPress 后台导出 xml
AI 解析 → 生成 Hugo Markdown + map 映射表 + SQL 脚本
上传 Hugo 仓库 → GitLab Runner 自动构建
配置 Nginx map → 301 重定向旧链接
执行 SQL → 评论数据也回来

最难的部分其实是 map 映射表——手动整理几百篇文章的对应关系不现实,但交给 AI 就是几分钟的事。迁移这件事本身没有太高的技术含量,就是脏活累活,AI 接手后人的工作只剩下审核和拍板。

迁移完成后,博客访问速度从几百毫秒变成毫秒级,SEO 权重靠 301 重定向大部分保留,后台编辑变成了写 Markdown 的清爽体验。

build with Hugo, theme Stack, visits 0