location /assets/ {
  add_header Cache-Control "public, max-age=31536000, immutable";
}
curl -I https://www.example.com/assets/app.8f3c2.js

打包产物 app.8f3c2.js 每次刷新都回源,Network 面板里 300 多个请求全是 304,首屏多花 400ms。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,expires 或 add_header 写成了 no-cache,浏览器每次都带 If-None-Match 来问。文件名已经带内容 hash,内容不会变,这种校验没有意义。

围绕「静态资源缓存头」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。

处理上按这个顺序:带 hash 的目录单独用 location 匹配 返回一年期的 immutable 缓存;index.html 反过来用 no-cache 保证发版能拿到新壳;add_header 要写在最终命中的 location 里 继承会覆盖;用 curl -I 看两个路径的缓存头是否分开。

改完只确认一件事:第二次刷新页面 Network 里静态资源显示 from disk cache 不再产生 304 请求。

作者 9823189