nginx用map按文件后缀设置缓存,先在http块中用正则映射$request_uri到$cache_time变量,再在location中用expires或add_header引用;推荐统一用add_header cache-control控制策略,兼顾immutable与兼容性。

直接用 map 指令按文件后缀设置缓存,核心是“先映射、再调用”:在 http 块中用正则匹配请求 URI 后缀,生成缓存时间变量;再在 server 或 location 中用 expires 或 add_header Cache-Control 引用该变量。它比写一堆 location ~ \.js$ { ... } 更简洁、易维护,也避免重复配置。
在 http 块中定义后缀到缓存时间的映射
必须放在 http 顶层,不能嵌套在 server 内。推荐用 $request_uri 匹配,稳定且无需依赖响应阶段变量:
- 正则加
~*确保不区分大小写,比如~*\.(js|css)$能匹配.JS和.Css - 把具体后缀规则放前面,通配或默认项放最后,否则会被
default拦截 -
"epoch"表示立刻过期(等效no-cache),"0"表示设为响应发出时刻(浏览器每次验证)
示例:
map $request_uri $cache_time {<br> default "epoch";<br> ~*\.(html|htm|php|xml)$ "0";<br> ~*\.(js|css|woff2|ttf|eot|svg|otf)$ "1y";<br> ~*\.(jpg|jpeg|png|gif|webp|avif)$ "1w";<br> ~*\.(ico|cur)$ "1m";<br>>
在 location 中应用缓存变量
只需一行 expires $cache_time,Nginx 就会自动根据请求后缀插入对应值。若需更精细控制(比如加 immutable),优先用 add_header:
-
expires会自动设置Expires和Cache-Control: max-age=头,但无法加immutable - 对带哈希的资源(如
app.a1b2c3.js),建议改用:add_header Cache-Control "public, immutable" always; -
always参数确保即使返回 304 或 4xx 也带上该头,避免缓存策略丢失
注意响应头覆盖逻辑
如果同时用了 expires 和 add_header Cache-Control,前者会覆盖后者中的 max-age,导致 immutable 失效。所以实际推荐:
- 统一用
add_header Cache-Control控制策略(含public、max-age、immutable) - 仅保留
expires $cache_time作兼容旧浏览器(如 IE)的Expires头 - 或者干脆只用
add_header,现代浏览器完全支持Cache-Control主导
避坑要点
几个高频出错点要盯紧:
- 正则里点号
.必须转义为\.,否则匹配任意字符,\.js$才是“以 .js 结尾” -
map不支持 if 或嵌套,所有逻辑必须靠正则顺序和 default 覆盖 -
expires只对 2xx/304 响应生效,4xx/5xx 不加头——这是正常行为,不用额外处理 - 若后端本身返回了
Cache-Control,需加proxy_ignore_headers Cache-Control;(反代场景)才能让 Nginx 的设置生效










