核心问题是代理层未尊重Nginx设置的缓存头,需确保Nginx对带hash的JS/CSS配置Cache-Control: public, immutable,并在CDN或反代中显式启用“遵循源站缓存头”、禁用HTML缓存、验证Age与Cache-Control响应头。

核心问题不在 Nginx 本身,而在于代理层(CDN、反向代理、公司网关)未尊重或覆盖了 Nginx 设置的缓存头。即使你已为带 hash 的 JS/CSS 配置了 Cache-Control: public, immutable,若 CDN 默认缓存所有静态资源且不透传响应头,旧文件仍可能被长期返回。
确保 Nginx 正确标记带 Hash 的资源
这是基础前提:只有 Nginx 先发出明确、合规的响应头,代理层才有依据可循。
- 匹配常见静态资源后缀,设置一年有效期 + immutable 属性
- 使用正则精确匹配,避免误伤 HTML 或 API 接口
- 确认
expires和add_header同时生效(Nginx 中expires会自动设置Cache-Control,但加immutable需显式用add_header)
示例配置:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
强制代理层识别并透传缓存策略
很多 CDN(如 Cloudflare、阿里云DCDN、腾讯云CDN)默认会覆盖源站的 Cache-Control,尤其对 .html 或未显式配置的路径。必须主动干预:
- 在 CDN 控制台中,为
*.js、*.css等扩展名单独设置「缓存过期时间:1年」并勾选「遵循源站缓存头」 - 检查 CDN 是否开启「缓存忽略参数」——这对带 hash 的资源是安全的,但需确认其不误删
immutable等关键指令 - 若使用公司自建反代(如 Nginx/LVS),确保其未在 upstream 中重写
Cache-Control头;可在 proxy_pass 后添加:
proxy_hide_header Cache-Control;
proxy_pass_request_headers on;
隔离 HTML 与静态资源的缓存生命周期
HTML 是唯一不带 hash 的入口文件,它一旦被代理层缓存,就会持续引用旧 hash 路径,导致“新 HTML 指向旧 JS”的错配。必须双重保障:
- Nginx 显式禁止 HTML 缓存:
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
} - 在 CDN 上将
*.html设为「缓存过期时间:0秒」或「不缓存」,并关闭「智能压缩」等可能修改响应体的中间处理 - 若使用 SPA,配合
try_files $uri $uri/ /index.html;时,确保该 location 块不位于静态资源匹配块之前,防止 HTML 请求被错误 fallback
验证代理层是否真正生效
不能只看浏览器 Network 面板——它显示的是最终响应,无法区分是源站还是 CDN 返回的。必须穿透代理直查:
- 用
curl -I https://yourdomain.com/app.a1b2c3.js,观察响应头中的Cache-Control和Age字段:
→ 若Age> 0,说明来自 CDN 缓存;
→ 若Cache-Control缺失immutable或 max-age 过短,说明 CDN 覆盖了源站头 - 临时在请求中加唯一 header(如
-H "X-Debug: 1"),并在 CDN 日志中确认该请求是否命中缓存 - 发布新版后,立即访问一个新 hash 的 JS 文件,用 curl 多次请求,观察
Age是否从 0 开始递增——若始终为 0,说明未缓存成功;若突增数百秒,说明缓存已生效但未及时刷新
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











