Hexo 博客从 NeXT 迁移到 Butterfly 的记录
这篇文章用于记录本站从 NeXT 主题迁移到 Butterfly 主题的过程,也顺便记录这次由 Codex 辅助完成的整理,排查,配置和验证工作。
这不是一篇从零开始的 Hexo 建站教程,而是一篇迁移复盘。对我来说,这次迁移最重要的目标不是把站点一次性改得多花哨,而是保证已有文章,图片,公式和页面结构都能在新主题下继续正常工作。
迁移目标
最开始的需求很明确:把当前使用的 NeXT 主题换成 jerryc127/hexo-theme-butterfly,同时尽量降低风险。
具体约束主要有几条:
- 已有博客内容必须继续正常渲染。
- 已有文章图片必须继续正常显示。
- 公式文章必须继续渲染正确,尤其不能被 Markdown 渲染器提前破坏。
- 优先使用 Butterfly 官方推荐方案。
- 移除 NeXT 主题和它的自定义残留。
- 使用 npm 安装主题,不再把主题 vendored 到
themes/下。 - 不迁移 NeXT 时代的外观自定义细节,先保证内容正常。
所以这次迁移不是简单把 _config.yml 里的 theme 从 next 改成 butterfly,而是围绕内容兼容性做了一轮完整检查。
版本选择
这次选择了 hexo-theme-butterfly@5.5.5。
Hexo 本身仍然保持在 6.3.0,没有顺手升级到新的大版本。原因很朴素:当前 Hexo 版本和站点插件已经可以正常配合 Butterfly 工作,而 Hexo 跨大版本升级可能牵动插件兼容性,对这次迁移目标没有直接收益。
最终依赖策略是:
- 新增
hexo-theme-butterfly。 - 新增 Butterfly 需要的
hexo-renderer-pug和hexo-renderer-stylus。 - 用
hexo-renderer-markdown-it-plus替换默认的hexo-renderer-marked。 - 保留现有稳定工作的 Hexo 主版本。
- 后续依赖升级不为升级而升级,只在有明确收益或安全修复时单独评估。
这个选择让主题迁移和框架升级解耦,排查范围也更可控。
主题迁移
主题安装改为 npm 方式,主题源码位于 node_modules/hexo-theme-butterfly/,不再放进 themes/ 目录。
站点配置中,_config.yml 负责 Hexo 本身的配置,例如站点地址,permalink,deploy 和 generator。Butterfly 主题自己的配置则放在 _config.butterfly.yml。这个文件是从主题默认配置复制出来的覆盖配置,Hexo 会自动合并它。
这次做的主题侧配置包括:
- 顶部导航。
- KaTeX 数学公式配置。
- 本地搜索配置。
- 首屏默认 banner。
- 头像和 favicon。
- 侧栏位置。
- GitHub,知乎和邮箱社交链接。
- 作者卡文案和公告。
- 自定义 CSS 注入。
NeXT 相关残留也被清理掉了,包括旧的 themes/next/ 和 NeXT 专用的 source/_data/ 自定义样式文件。这些文件已经不再被 Butterfly 读取,留着只会增加误导。
图片处理
图片是这次迁移里最需要谨慎确认的部分之一。
本站开启了 post_asset_folder: true,文章图片放在同名资源文件夹里,例如 foo.md 对应 foo/image.png,文章中用相对路径引用。过去 NeXT 时代站点配置里有 marked.prependRoot 和 marked.postAsset 相关配置,但这属于旧渲染链路的一部分。
迁移后图片主要依赖 hexo-asset-img。这个插件会在 Markdown 渲染之前通过 Hexo 的 before_post_render 阶段处理图片路径,把相对图片链接转换成 Hexo 的 asset 标签,最终输出站点根路径下的图片地址,例如 /post/foo/image.png。
这意味着图片处理不依赖具体 Markdown 渲染器。因此,后面把 hexo-renderer-marked 换成 hexo-renderer-markdown-it-plus 时,图片链路没有被一起改坏。
迁移验证时重点检查了已有文章图片的输出路径和访问状态,确认图片仍能正常显示。
公式处理
公式问题是这次迁移里最关键的一处排查。
一开始如果继续使用 hexo-renderer-marked,数学公式中的 * 和 _ 可能会先被当作 Markdown 强调语法处理。例如公式中的乘号附近内容会被错误渲染成 <em> 标签。一旦 HTML 已经被破坏,主题侧再用 MathJax 或 KaTeX 都很难挽救。
最终采用 Butterfly 推荐路线:用支持数学语法的 hexo-renderer-markdown-it-plus 替换默认 marked 渲染器,并在 Butterfly 中配置 KaTeX。
当前方案是:
_config.butterfly.yml中设置math.use: katex。math.per_page: false,让主题按文章 front matter 决定是否加载公式资源。- 含公式文章使用
katex: true。 - 不再使用
mathjax: true。 - 不保留
_config.yml中旧的marked:配置段。
验证结果是公式在构建时已经被服务端渲染为带 class="katex" 的 HTML,不再依赖浏览器端去修复一段已经损坏的公式文本。
视觉复刻
主题迁移完成后,又做了一轮很克制的视觉复刻。
这里没有尝试把 NeXT 的所有样式细节搬到 Butterfly。只恢复了几个对站点识别度比较重要的元素:
- 使用原来的雪湖头像。
- 恢复 favicon 和 apple touch icon。
- 恢复顶部 banner 图。
- 侧栏在宽屏下左置。
- 恢复作者卡描述。
- 恢复 GitHub,知乎和邮箱链接。
- 关闭头像和社交图标 hover 时的旋转效果。
头像和 favicon 的原始资源当时并不在源码仓里,后来是从 .deploy_git/uploads/ 中找回的。.deploy_git/ 虽然是生成产物,平时不应该提交或手工编辑,但在这种源码仓缺失旧线上资源的情况下,它正好提供了一份可恢复的历史副本。
自定义样式没有直接改主题源码,而是写在 source/css/custom.css,再通过 Butterfly 的 inject.head 注入。其中有一个细节是 Butterfly 的部分 hover 样式选择器权重很高,覆盖时需要使用同等或更高权重的选择器,必要时加 !important。
自动部署
迁移上线之后,又补上了自动部署流程。
现在源码仓 SnowyLake/BlogSource 每次 push 到 main 后,GitHub Actions 会自动运行:
1 | npm ci |
npm run deploy 仍然复用 Hexo 原有的 hexo deploy,它会把生成的 public/ 推送到 SnowyLake/snowylake.github.io 的 main 分支。这样对原有部署方式改动最小,只是把本地手动执行变成了云端自动执行。
为了让 Actions 能推送 Pages 仓库,这次没有复用本机常用 SSH key,而是单独创建了一把 deploy key:
- 公钥添加到
SnowyLake/snowylake.github.io的 Deploy keys,并允许写入。 - 私钥保存到
SnowyLake/BlogSource的 Actions secretHEXO_DEPLOY_KEY。 - 本地临时私钥文件在配置完成后删除。
后来 GitHub Actions 出现过 Node.js 20 is deprecated 的 warning。排查后确认,这个 warning 来自 GitHub JavaScript action 自身运行时,不是 Hexo 构建使用的 Node 版本。因此最终升级的是 workflow 中的 action 版本:
actions/checkout@v7。actions/setup-node@v6。webfactory/ssh-agent@v0.10.0。
升级后自动部署重新跑通,Node 20 action runtime warning 消失。npm 依赖链里仍有一些 deprecated package 提示,但它们不阻塞构建和部署,可以以后单独评估。
最后的状态
这次迁移完成后,站点处于一个更清晰的状态:
- Hexo 仍保持稳定的
6.3.0。 - 主题切换为 npm 安装的 Butterfly。
- 主题配置集中在
_config.butterfly.yml。 - 公式渲染改为 KaTeX +
hexo-renderer-markdown-it-plus。 - 图片继续通过
hexo-asset-img和文章资源文件夹处理。 - NeXT 主题和对应残留已经移除。
- 自动部署由 GitHub Actions 接管。
还有一些后续可以慢慢做的事,例如建立文章封面系统,给页面配置专属 banner,补 RSS feed,或者把旧的建站记录补上一段历史说明。
但这次迁移本身的核心目标已经完成:不追求一次性重做整个站点,先让已有内容在新主题下稳定,正确,可维护地继续存在。
