静态资源更新后浏览器仍加载旧文件,核心是URL和缓存头未变;解决方法为:①文件名加内容哈希实现长缓存,②HTML等设协商缓存强制验证,③调试时临时禁用缓存,④排查sendfile干扰。

静态资源更新后浏览器仍加载旧文件,核心矛盾在于URL没变 + 缓存头没变 + 浏览器认定资源未更新。Nginx 本身不“通知”浏览器刷新,必须靠主动设计让浏览器感知变化。解决方向就两条:让新资源变成“新地址”,或让浏览器每次请求都去确认一遍。
给静态文件加内容哈希(最推荐)
这是工业级项目首选,一劳永逸,兼容 CDN 和所有代理。
- 构建时用 Webpack/Vite 启用
contenthash,生成类似app.a1b2c3.js、style.f4e5d6.css的文件名 - HTML 中直接引用带哈希的路径:
<script src="/js/app.a1b2c3.js"></script> - Nginx 配置中对这些后缀设长缓存:
location ~ \.(js|css|png|jpg|gif|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
强制浏览器重新验证(适合 HTML 或无法改名的资源)
不禁止缓存,而是让浏览器每次请求都发一个验证请求,服务端根据文件是否真变了决定返回 200 还是 304。
- 对
.html类资源设短有效期 + 协商缓存:
location ~ \.html$ {
expires 1m;
add_header Cache-Control "public, must-revalidate";
add_header Last-Modified $date_gmt;
etag on;
} - 确保 Nginx 能读取文件真实修改时间(
$date_gmt是内置变量,需配合log_format或启用if_modified_since)
临时禁用缓存(仅限调试阶段)
上线前验证逻辑没问题时可用,但切勿长期开启,会显著增加服务器压力和用户延迟。
- 在静态资源 location 块中加入:
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
expires -1; - 注意:该配置优先级高于全局设置,建议只匹配具体后缀,如
location ~ \.(js|css|html)$
检查 Nginx 是否启用了 sendfile 导致内核绕过缓存更新
sendfile 开启时,Nginx 直接通过内核零拷贝发送文件,可能跳过部分用户态缓存刷新机制,尤其在频繁热更新场景下容易“卡住”旧版本。
- 临时排查可先关闭:
sendfile off; - 若确认是此问题,长期方案不是关 sendfile(影响性能),而是搭配哈希文件名 + 长缓存,让 sendfile 安全高效地服务不变的资源


















