静态站的缓存头:带哈希的永久,HTML 一律不缓存

缓存策略只取决于文件名是否随内容变化,与文件大小无关。HTML 长缓存会让用户拿到旧入口、指向已删除的旧 chunk,是静态站最常见的线上白屏。

静态站上线之后最先暴露的问题不是速度,而是部署完之后页面白屏。原因几乎总是同一个:HTML 被缓存了,但它引用的资源文件名已经变了。

判断依据只有一条

「这个文件名会随内容变化吗?」会,就可以永久缓存;不会,就必须每次校验。跟文件大小、访问频率都无关。

构建产物分三类:

路径 文件名 缓存策略
/_astro/* 带内容哈希 max-age=31536000, immutable
*.html 固定 no-cache
/pagefind/* 混合 max-age=3600

为什么 HTML 不能长缓存

构建是原子的:一次 npm run build 会输出新的哈希文件名并删掉旧的。index.html 是唯一入口,如果它被浏览器缓存一年,用户打开的是上一次部署的 HTML,里面写着的 /_astro/index.abc123.js 在新部署里已经不存在 —— 结构和样式能出来,脚本 404,交互全失效。

no-cache 不是「不缓存」,而是「每次带 ETag 回来问一次」。命中时服务器回 304,正文不重传,成本是一个往返,换来的是永远不会引用到已删除的哈希。

location ~* ^/_astro/ {
  add_header Cache-Control "public, max-age=31536000, immutable";
}

location ~* \.html$ {
  add_header Cache-Control "no-cache";
}

两个容易漏的地方

  • Pagefind 的索引目录:pagefind.js 不带哈希,其余分片带。统一给一小时,既能跟上重建,也不至于每次搜索都重下几 MB。
  • sw.js / manifest 之类约定俗成的入口:本站不做 PWA,所以没有这一类;如果做了,它们和 HTML 同级 —— 文件名不变,就不能长缓存。

别问「这个文件大不大」,问「改内容之后文件名会不会变」。

← 返回文章列表

评论

…