Knighthana
文章113
标签153
分类7

文章归档

博客构建与部署时间优化记录

博客构建与部署时间优化记录

博客构建与部署时间优化记录

博客构建链路改造记录把”构建”搬进 GitHub Actions 之后,构建环节又花了两天优化时间消耗。这篇文章记录三个优化点、一个踩坑、以及实测数据。

背景:从日志里发现的问题

某次 CI 构建的 Generate site 步骤日志暴露了三个现象:

1
2
3
INFO  Files loaded in 9.85 s
INFO 458 files generated in 1.38 s
Inferno is in development mode.
  • Files loaded 9.85s:112 篇文章全量处理,占总耗时大头
  • Inferno is in development mode:主题前端框架的提示噪音
  • 全站每篇文章都过了一遍 MathJax 服务端渲染(every_page: true),大量不含公式的文章白白消耗

针对这三点的优化依次落地。

优化一:CI 缓存 hexo 数据库,启用增量生成

hexo 的 db.json 记录了每篇文章的处理结果与文件 mtime,配合 updated_option: mtime 就能做增量:文件没变就不重新渲染。之前 CI 每次 npm ci 都是全新工作区,没有 db.json,于是每次都是全量。

仓库里已有的 restore-mtime 步骤(用 git 提交时间恢复文件 mtime)为增量提供了前提——只要 db.json 在,hexo 就能判断哪些文章变过。

在 workflow 里加了缓存步骤:

1
2
3
4
5
6
- name: Cache hexo db
uses: actions/cache@v6
with:
path: builder/db.json
key: hexo-db-${{ hashFiles('builder/package-lock.json','builder/_config.yml','builder/_config.nexmoe.yml','builder/patches/**','builder/scripts/**') }}
restore-keys: hexo-db-

关键点是 cache key 不包含 raw/ 内容:绑定依赖、配置和补丁,但刻意不绑文章内容。这样只改一篇文章时缓存仍然命中,hexo 只重渲染这一篇,而不是重新全量。

优化二:MathJax 按需渲染

_config.yml 里原本 every_page: true——每页都过 MathJax。改成 false 之后,没有显式 mathjax: true 的页面不会触发渲染,但手写 front-matter 标记太麻烦,于是写了一个自动检测脚本:

1
2
// builder/scripts/mathjax-autodetect.js
// 检测渲染后的内容是否含行内/块级公式分隔符,是则启用 MathJax

脚本在 after_post_render 阶段扫描渲染结果,发现行内/块级公式标记就自动开启 MathJax;如果文章显式写了 mathjax: false,则尊重作者意图不覆盖。

效果:112 篇文章里真正含公式的只有 9 篇需要 MathJax,其余 103 篇直接跳过,省掉了大部分渲染成本。

踩坑:pandoc 换行把图片属性拆断了

MathJax 关掉后,本地对比构建产物时发现图片的 fancybox 属性丢失。排查半天,根因在 pandoc 的默认换行行为:

  • 主题的 image_filter.js 用单行正则匹配 <img src="..." alt="...">
  • pandoc 默认在 72 列处换行,会把 <img src="...">alt="..." 拆到两行
  • 正则匹配不到,图片就丢了 fancybox 的增强属性
  • 之前 every_page: true 时 MathJax 的 DOM 往返会重新序列化、把标签拼回一行,掩盖了这个问题;关掉之后暴露出来

修复:给 pandoc 加 --wrap=none,保持单行输出:

1
2
3
4
pandoc:
args:
--mathjax
--wrap=none

验证:产物中 fancybox 属性计数与改造前完全一致。

优化三:消除 Inferno 开发模式提示

Inferno is in development mode. 是 Inferno 检测到 NODE_ENV 未设置时的提示。给 Generate site 步骤加上环境变量即可消除:

1
2
3
4
5
- name: Generate site
working-directory: builder
env:
NODE_ENV: production
run: npx hexo generate

实测数据

指标 改造前 改造后
本地全量 Files loaded 16-18s ~12s
本地增量 Files loaded(db 命中) 1.21s
CI Files loaded 9.85s 4.86s(cache miss 全量)
CI 458 files generated 1.38s 0.93s
CI Generate site 步骤 ~12s ~6s
单篇改动增量重渲染 全量 +0.67s,只重渲染该篇

说明:上面 CI 的 4.86s 是首次跑(cache miss,仍为全量构建,但已享受 MathJax 按需渲染的收益);后续 db.json 缓存命中后 Files loaded 会进一步降到 1-2s 量级。

正确性验证

  • 数学文章集合与改造前完全一致(9 篇含 SVG 渲染,其余无 mjx-container)
  • 图片 fancybox / onerror / lazy 属性计数一致(2106 img 中 36 个带 fancybox,与改造前相同)
  • 产物语义对比 368 个文件无功能差异

遗留观察

  • babel 弃用警告:日志里仍有 Usage of builders starting with an uppercase letter such as 'ObjectExpression' has been deprecated。来自主题 JSX 编译链路 babel-plugin-inferno 调用了 @babel/types 的旧式大写 builder 名。仅警告、不影响产物,属于 node_modules 内部问题,暂不处理。
  • 同日文章排序波动:归档/分类/atom 中,日期完全相同的文章相对顺序在全量重建时可能互换(hexo 同日排序不稳定)。与本次改动无关,属既有行为。
  • ?v= 时间戳:主题给资源 URL 打毫秒级时间戳做缓存失效,导致每次 generate 都会重写引用这些资源的页面。CI 上无影响,未纳入改动。

Knighthana & DeepSeek

2026/09/04