Nginx中add_header Cache-Control需动态配置:按路径区分静态资源(public, immutable, max-age=1y)与API(no-store, no-cache);利用map变量、$status条件及always参数实现精准控制,避免继承覆盖和304失效。

在 Nginx 中通过 add_header Cache-Control 设置缓存策略,看似简单,但直接写死值容易导致缓存失效或内容陈旧。真正有效的做法是结合 location、if、变量和响应状态码,实现按路径、文件类型、用户身份甚至后端逻辑动态控制缓存行为。
区分静态资源与动态接口:基础分层策略
静态资源(如 JS/CSS/图片)适合强缓存,而 API 接口通常禁用缓存或使用协商缓存:
- 对
/static/和常见后缀(.js、.css、.png等),用expires 1y+add_header Cache-Control "public, immutable",既延长有效期又避免重复校验 - 对
/api/或/v1/开头的路径,统一加add_header Cache-Control "no-store, no-cache, must-revalidate",确保敏感数据不落本地 - 注意:
add_header在子块中会覆盖父块,所以需在最内层 location 中明确设置,避免继承意外值
按用户角色或登录态差异化缓存
未登录用户看到的首页可缓存 5 分钟,而登录后个人中心页面应禁止缓存:
- 利用 Nginx 变量识别请求特征,例如从 cookie 提取
user_id:
map $cookie_user_id $cache_policy { "" "public, max-age=300"; default "no-cache, private"; } - 再在对应 location 中写:
add_header Cache-Control $cache_policy; - 若后端通过响应头(如
X-Auth-State: logged-in)传递状态,可用$sent_http_x_auth_state变量做判断
根据后端响应状态码自动调整缓存强度
成功响应可缓存,错误页(404/500)默认不缓存,但某些降级页(如维护页)反而需要短时缓存减轻压力:
- 使用
proxy_cache_valid更合适处理状态码缓存,但若仅用add_header,可通过if ($status = 200)配合add_header实现条件添加 - 示例:
if ($status = 200) { add_header Cache-Control "public, max-age=600"; }
if ($status = 503) { add_header Cache-Control "public, max-age=60"; } - 注意:
if在 location 中才安全;避免在 server 级别滥用,且不能嵌套
规避常见陷阱:Header 覆盖与浏览器兼容性
add_header 不会追加,而是替换同名 header;且它不作用于 304 响应——这是最容易被忽略的点:
- 若上游服务已返回
Cache-Control,Nginx 默认不会覆盖,需加always参数强制添加:
add_header Cache-Control "no-cache" always; - 对 304 响应,浏览器只信任原始响应中的缓存头,Nginx 的
add_header完全无效,此时必须靠expires或后端控制 - 移动端 WebView 对
immutable支持不一,生产环境启用前建议灰度验证










