nginx需按资源类型、请求特征和响应状态动态设置cache-control并强制生效:①分类匹配(哈希资源设immutable,普通静态资源must-revalidate,html禁强缓存);②条件注入(依登录态、状态码、ip段动态赋值);③加always确保覆盖上游头且作用于非200响应。

Linux 下 Nginx 通过 Cache-Control 响应头实现精确缓存控制,核心不是“加一个头”,而是按资源类型、请求特征和响应状态动态设置指令,并确保它真正生效。关键在三点:分类匹配、条件注入、强制覆盖。
按文件类型和路径精准匹配
不同静态资源更新频率差异极大,必须分层配置:
-
带哈希指纹的资源(如
app.a1b2c3.js、style.f4e5d6.css):内容不变则路径不变,适合永久强缓存location ~* "\.[a-f0-9]{8,}\.(js|css|png|jpg|gif|svg|woff2?)$" {<br> add_header Cache-Control "public, max-age=31536000, immutable" always;<br> access_log off;<br> } -
普通静态资源(如
/images/logo.png、/fonts/icon.woff):变动较少但无哈希,需保留验证能力location ~* \.(png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$ {<br> add_header Cache-Control "public, max-age=2592000, must-revalidate" always;<br> } -
HTML 文件:入口页极易因 JS/CSS 更新而失效,必须禁用强缓存
location ~* \.html$ {<br> add_header Cache-Control "no-cache, must-revalidate" always;<br> }<br> location = / {<br> try_files /index.html =404;<br> add_header Cache-Control "no-cache" always;<br> }
用变量和条件实现动态策略
缓存不能一刀切,要结合业务逻辑实时判断:
-
按用户登录态区分:未登录首页可缓存,个人中心禁止缓存
map $cookie_user_id $cache_policy {<br> "" "public, max-age=300";<br> default "no-cache, private";<br> }<br> location / {<br> add_header Cache-Control $cache_policy always;<br> } -
按后端响应状态码调整:成功响应可缓存,降级页(如 503)也值得短时缓存
if ($status = 200) {<br> add_header Cache-Control "public, max-age=600" always;<br> }<br> if ($status = 503) {<br> add_header Cache-Control "public, max-age=60" always;<br> } -
按 IP 段差异化控制:内网用户可设长缓存,外部用户设保守策略
geo $internal_ip {<br> default 0;<br> 192.168.0.0/16 1;<br> 10.0.0.0/8 1;<br> }<br> location ~* \.(js|css|png)$ {<br> add_header Cache-Control $internal_ip "public, max-age=3600" "no-cache" always;<br> }
确保 header 真正写入且不被覆盖
Nginx 默认不会覆盖上游已设的 Cache-Control,也不作用于 304 响应——这是最常出错的地方:
- 必须加
always参数,否则对 304、206、404 等非标准 200 响应无效 - 若后端(如 PHP、Node.js)已返回
Cache-Control,Nginx 的add_header默认不替换,always是强制生效的关键 - 避免在父块(如
server)中设置通用add_header,否则会被子location继承覆盖;应在最内层location显式声明 - 上线后务必用浏览器 DevTools 的 Network 面板验证:检查实际响应头是否含预期值,尤其注意 HTML 是否真的为
no-cache,哈希文件是否含immutable
不推荐只依赖 expires 指令
expires 会自动生成 Expires 和基础 Cache-Control: max-age=,但它无法添加 public、immutable、must-revalidate 等关键语义。例如:expires 1y; → 只生成 Cache-Control: max-age=31536000,缺少 public 则 CDN 不会缓存;
而 add_header Cache-Control "public, max-age=31536000, immutable" always; 才完整表达意图。











