博客构建与部署时间优化记录
博客构建与部署时间优化记录
在博客构建链路改造记录把”构建”搬进 GitHub Actions 之后,构建环节又花了两天优化时间消耗。这篇文章记录三个优化点、一个踩坑、以及实测数据。
背景:从日志里发现的问题
某次 CI 构建的 Generate site 步骤日志暴露了三个现象:
1 | INFO Files loaded in 9.85 s |
- 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 | - name: Cache hexo db |
关键点是 cache key 不包含 raw/ 内容:绑定依赖、配置和补丁,但刻意不绑文章内容。这样只改一篇文章时缓存仍然命中,hexo 只重渲染这一篇,而不是重新全量。
优化二:MathJax 按需渲染
_config.yml 里原本 every_page: true——每页都过 MathJax。改成 false 之后,没有显式 mathjax: true 的页面不会触发渲染,但手写 front-matter 标记太麻烦,于是写了一个自动检测脚本:
1 | // builder/scripts/mathjax-autodetect.js |
脚本在 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 | pandoc: |
验证:产物中 fancybox 属性计数与改造前完全一致。
优化三:消除 Inferno 开发模式提示
Inferno is in development mode. 是 Inferno 检测到 NODE_ENV 未设置时的提示。给 Generate site 步骤加上环境变量即可消除:
1 | - name: Generate site |
实测数据
| 指标 | 改造前 | 改造后 |
|---|---|---|
| 本地全量 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