expires仅在http、server、location块中生效,遵循“最近匹配location优先”覆盖规则,不可用于upstream等块;推荐按资源类型拆分include文件,并用map+add_header实现动态缓存控制。

在 Nginx 多级 include 配置中,expires 指令的生效逻辑和维护难点主要来自作用域覆盖、配置加载顺序与上下文限制。它不能在所有块中使用,且子配置中重复定义易引发意外覆盖或静默失效。
明确 expires 的可用上下文与继承规则
expires 只能在 http、server、location 块中使用,不支持 在 upstream、map 或自定义指令块中出现。多级 include 下,它的行为遵循“最近匹配 location 优先”原则:即使 http 块里设了全局缓存,某个 location 中又写了 expires off,该路径就完全禁用缓存头。
- 若在
http块include的公共文件中设置expires 1h,它仅作为默认值,可被下层server或location中的同名指令覆盖 -
location ~* \.(js|css)$内的expires 1y会覆盖更外层的设置,且只对匹配的后缀生效 - 注意:
expires不影响代理响应(如proxy_pass后端返回的Cache-Control),除非显式加proxy_ignore_headers Cache-Control;
拆分 expires 配置到语义化 include 文件
避免把所有 expires 规则堆在一个大文件里。按资源类型或业务模块拆分,例如:
-
expires-static.conf:专用于静态资源(图片、字体、JS/CSS),放在location块内 -
expires-api.conf:针对 API 接口,通常设为expires epoch或off -
expires-vue-spa.conf:单页应用的 HTML 设短缓存(10m),其他资源设长缓存
每个文件开头加注释说明适用范围和预期效果,便于协作时快速定位。引入时保持层级清晰,比如在 server 块末尾统一 include conf.d/expires/*.conf;,而非分散在多个位置。
用 map + add_header 替代部分 expires 场景
当需要基于变量(如请求参数、Header、上游响应码)动态控制缓存头时,expires 无能为力。此时应改用 map 定义变量,再配合 add_header:
- 在
http块中定义:map $sent_http_content_type $cache_control_value {<br> default "public, max-age=3600";<br> "application/json" "no-cache";<br> "text/html" "public, max-age=600";<br>} - 在
location中写:add_header Cache-Control $cache_control_value always; -
always参数确保即使响应码非 2xx 也添加头,弥补expires对非 2xx 响应不生效的缺陷
上线前必须验证的三项检查
多级 include 容易漏掉某一层的覆盖或语法错误,发布前建议逐项确认:
- 运行
nginx -t并检查输出中是否提示expires出现在非法上下文(如出现在if块内) - 用
curl -I测试典型路径,比对响应头中的Expires和Cache-Control是否符合预期,特别关注 304、404、500 等非标准状态码下的表现 - 检查
nginx -T(全量展开配置)输出,搜索目标 location 块,确认最终生效的expires行来自哪个 include 文件,排除被意外覆盖

















