浏览器不缓存主因是响应头冲突,如后端返回Cache-Control: no-cache会覆盖Nginx的expires配置;需用curl -I查真实响应头,检查Cache-Control、Expires等是否合法,并通过日志确认Nginx是否被错误头“带偏”,必要时用proxy_ignore_headers忽略上游头。

浏览器不缓存,往往不是 Nginx 没配缓存,而是响应头之间互相打架——比如后端返回了 Cache-Control: no-cache,而你又在 Nginx 里写了 expires 1y,结果 Nginx 默认听后端的,直接放弃缓存。排查关键在于“谁说了算”和“它到底发了什么”。
先看真实响应头,别信配置文件
用 curl -I 直接请求目标 URL,观察原始响应头:
- 重点检查
Cache-Control、Expires、ETag、Last-Modified是否存在、是否合法(比如max-age=后面没数字,或含空格/控制字符) - 如果返回
Cache-Control: no-store, no-cache或max-age=0,Nginx 默认不会缓存该响应,哪怕你配了proxy_cache_valid - 若
Expires是过去时间(如Expires: Wed, 01 Jan 1990 00:00:00 GMT),同样触发不缓存逻辑
确认 Nginx 是否被后端头“带偏”了
Nginx 默认信任上游响应头,但有时这恰恰是问题根源:
- 查日志:开启
log_format记录$upstream_http_cache_control和$upstream_cache_status,观察是否频繁出现BYPASS或为空值 - 如果日志中
$upstream_http_cache_control显示非法值(如max-age=、no-cache,带多余空格),说明 Nginx 因格式错误丢弃了整条 Cache-Control - 此时可临时加
proxy_ignore_headers Cache-Control Expires;(放在location内、proxy_pass后),让 Nginx 忽略后端的错误头,转而依赖你配置的proxy_cache_valid
检查 Nginx 缓存指令是否生效范围正确
缓存相关指令必须落在真正处理请求的 location 块内,且不能被覆盖:
-
proxy_cache_valid 200 302 10m;只对状态码匹配的响应生效;若后端返回 201 或 304,需单独写明 -
expires和add_header Cache-Control默认只作用于 2xx/3xx 响应;对 4xx/5xx 或 304 不生效,容易误判“缓存没起作用” - 避免在
http块全局写expires,它可能被子块中的proxy_pass或try_files绕过;建议统一在具体location中配置
验证浏览器是否真的收到缓存友好头
即使 Nginx 缓存了,浏览器也可能因响应头矛盾拒绝缓存:
- 用
curl -I确认最终返回的响应头是否含Cache-Control: public, max-age=3600(或类似合理值),而非private或no-cache - 若后端返回
Set-Cookie,Nginx 默认不缓存(除非显式加proxy_ignore_headers Set-Cookie),且浏览器会将响应视为 private,强制不缓存 - 确保
add_header加了always参数,例如:add_header Cache-Control "public, max-age=3600" always;,否则 304 响应不会带这个头,浏览器无法复用


















