内容指纹 + 输出复用:博客增量构建缓存的设计
博客有 67 篇文章,每篇要经过 Markdown 渲染、代码高亮、公式转换、图片 WebP 转码等步骤。每次全量构建即使只改了一篇文章,也要把所有步骤重跑一遍。
核心思路:如果源文件没变、输出已存在,就跳过。
三层缓存判定
第一层:版本号
缓存文件 .blog-cache.json 里带一个 version 字段。构建脚本版本升级时,意味内部逻辑可能变化(比如新增了 WebP 转换、路径重写规则调整),此时旧缓存全部作废,触发全量重建。
第二层:目录指纹
每篇文章是一个目录,包含 index.md 和图片等资源。计算指纹时,遍历目录下所有文件,取出文件名、字节大小、最后修改时间的毫秒值,拼成一个字符串再 SHA-256 截取 16 位:
文件名:大小:修改时间ms | 文件名:大小:修改时间ms | ...
↓ SHA-256 → 16 hex文件增删、内容变化、重命名都会改变指纹。指纹相同意味着整篇文章的源输入与上一次构建完全一致。
第三层:输出存在性
即使指纹命中,还要确认 public/posts/{文章}/index.html 真实存在。防止因手动清理输出目录或部分构建失败导致的虚假命中。
同时,扫描完所有文章后,反向检查输出目录——如果某个输出目录找不到对应的源文章,说明文章已被删除,自动清理。
什么被缓存
指纹命中时,整条渲染链路全部跳过:
- Markdown 解析与 Shiki 代码高亮
- KaTeX 公式渲染
- sharp 图片 WebP 转码
- 封面压缩
- HTML 页面生成
- 文件复制
直接将缓存的文章元数据(标题、描述、标签、分类等)推入 posts.json 的构建列表。
命中效果
实测:67 篇文章首次全量构建后,第二次构建 67/68 命中缓存。修改一篇文章再构建,只有被改的文章触发重建,其余 66 篇全部跳过。构建时间从秒级降到毫秒级。
本文由 AI 辅助生成,可能存在错误或遗漏,请以实际资料和官方文档为准。