nginx 中静态资源缓存需精准配置 cache-control:带哈希的资源用 public,max-age=31536000,immutable;html 用 no-cache,must-revalidate;无版本号资源用 public,max-age=86400,must-revalidate;优先 add_header 而非 expires,并确保 location 匹配正确。

在 Nginx 中为静态资源设置响应缓存策略,核心是让浏览器和中间代理(如 CDN)明确知道“能不能缓、缓多久、要不要验证”。这不是简单加个 expires 就能搞定的事,关键在于用对 Cache-Control 指令,并匹配资源特性。
按资源类型精准设置 Cache-Control
不同静态文件更新频率差异大,应分类配置,避免“一刀切”:
-
带哈希指纹的 JS/CSS/字体/图片(如
app.a1b2c3.js):内容不变,可长期强缓存add_header Cache-Control "public, max-age=31536000, immutable"; -
HTML 文件:通常随版本发布更新,必须禁止强缓存或设极短时效
add_header Cache-Control "no-cache, must-revalidate";或"private, max-age=0" -
未带版本号的通用资源(如
/logo.png):可设中短期缓存,留验证余地add_header Cache-Control "public, max-age=86400, must-revalidate";
优先用 add_header,慎用 expires
expires 指令会同时生成 Expires 和基础 Cache-Control: max-age=...,但它无法添加 public、immutable、must-revalidate 等关键指令。生产环境推荐统一用 add_header:
- 直接控制响应头内容,语义清晰
- 配合
always参数可覆盖上游(如 FastCGI)已设的缓存头 - 注意:默认情况下
add_header不继承父块,需在每个匹配的location内显式声明
确保 location 规则真正生效
Nginx 的 location 匹配有严格优先级:= > ^~ > 正则(~ / ~*) > 前缀路径。常见失效原因是缓存配置写在正则 location 里,但实际请求被更高优先级的 ^~ 或 = location 拦截了。
- 用
nginx -T查看最终生效的配置树,确认缓存指令落在实际命中 location 中 - 若使用
alias或root服务静态文件,缓存头必须写在该 location 块内 - 避免在外部 server 块或 http 块中全局写
add_header,易被覆盖或误用
搭配其他优化提升缓存实效性
光设响应头还不够,需协同机制保证缓存行为可靠:
-
启用
sendfile和tcp_nopush:减少内核态拷贝,提升大文件传输效率 -
开启
open_file_cache:缓存文件元信息(存在性、权限、inode),降低磁盘 stat 开销 -
添加调试头:
add_header X-Cache-Status $upstream_cache_status;(用于代理场景)或X-Static-Cache自定义标识,方便排查是否命中 -
避免冲突指令:不要在同一个 location 同时用
expires和add_header Cache-Control,以防语义混乱











