expires指令不继承,只在匹配的location块内生效,遵循“最近匹配location优先”原则;Nginx不支持location嵌套,所有location平级,请求仅匹配唯一最精确块。

expires 指令在 location 嵌套块中不继承,只覆盖。它没有父子传递逻辑,一个请求最终生效的 expires 值,只取决于**匹配到的那个 location 块内是否显式声明了 expires**,其他外层(包括父级 location)的设置完全不生效。
location 块之间互不嵌套,所谓“嵌套”是视觉错觉
Nginx 实际不支持 location 块的物理嵌套(即不能在 location 内再写一个 location 块)。配置中看到的缩进或层级只是书写习惯,所有 location 都平级存在于 server 块下。Nginx 在运行时按匹配优先级选出**唯一一个**最精确匹配的 location 块来处理请求。
- 例如:
location /api/ { ... }和location ~ \.json$ { ... }是两个独立块,不是父子关系 - 即使 URI 是
/api/v1/data.json,也只会进入其中一个——按规则选最长前缀匹配或最高优先级正则,不会“先进入 /api/,再进入 .json” - 因此不存在“父 location 的 expires 传给子 location”的机制
生效只看匹配位置,越靠近匹配点优先级越高
expires 是 Normal 类指令,遵循“最近匹配 location 优先”原则。它的作用域就是它所处的那一个 location 块,不会向上继承,也不会向下穿透。
- server 块里写了
expires 1h;→ 对未被任何 location 匹配的请求生效 - location /static/ 里写了
expires 1y;→ 所有匹配该 location 的请求(如 /static/logo.png)用 1 年 - location ~* \.(js|css)$ 里写了
expires off;→ 即使它和 /static/ 有路径重叠(如 /static/app.js),只要正则匹配成功,就用 off,server 或 /static/ 里的设置全部失效
常见误操作与规避方式
很多人试图用“嵌套思维”写配置,结果缓存行为失控。典型问题包括:
- 在
location /assets/ { ... }中设expires 1w;,又在同 server 下另写location ~* \.svg$ { expires 1y; },但 SVG 文件仍走 1 周——因为两个 location 是并列的,而 /assets/icon.svg 可能只匹配到前缀 location,根本没进正则块 - 把 expires 放在 upstream 或 map 块里 → 直接报错,语法不合法
- 依赖 http 块全局设置,却忘了某个 server 完全没写 location,导致静态资源缓存策略缺失
推荐做法:对关键资源类型,统一用正则 location 显式覆盖,避免靠前缀 location “顺带”控制;必要时结合 map + add_header 实现更灵活的条件缓存。










