推荐用 map 指令按 $request_uri 后缀动态设 expires,定义在 http 块中,通过正则提取小写后缀并映射缓存时长,再于 location 中用 expires $expires_time 统一启用,简洁易维护。

直接用 map 指令按文件后缀动态设置 expires,核心在于把“后缀”映射成“缓存时长”,再在 location 中引用。这种方式比一堆重复的 location ~* \.xxx$ 更清晰、易维护,尤其适合后缀多、规则有分组逻辑的场景。
map 必须定义在 http 块中,且匹配 $request_filename 或 $uri 后缀
不同于按 Content-Type 映射(需依赖 $sent_http_content_type),按后缀映射更早、更可控,推荐使用 $request_uri 或 $uri 提取扩展名:
- 用正则从请求路径提取后缀,例如
~* \.([a-z0-9]+)(?:\?|$),捕获组$1就是后缀 - map 块中对常见后缀逐条设定缓存时间,未匹配的设为默认值(如
-1) - 注意大小写:后缀通常小写,建议统一转小写后再匹配,或用
~*不区分大小写
典型配置示例:按后缀分三级缓存策略
以下配置放在 http{...} 块内:
map $request_uri $expires_time {
default "-1";
~*\.html?$ "-1";
~*\.php$ "-1";
~*\.js$ "1M";
~*\.css$ "1M";
~*\.woff2?$ "1y";
~*\.ttf$ "1y";
~*\.png$ "7d";
~*\.jpg$ "7d";
~*\.webp$ "30d";
~*\.svg$ "7d";
}
然后在 server 或具体 location 中启用:
location / {
expires $expires_time;
# 可选:补充 Cache-Control 策略
add_header Cache-Control "public" always;
}
这样所有请求都会根据 URL 后缀自动获得对应缓存时长,无需为每类资源单独写 location。
配合哈希文件实现强缓存 + 安全更新
对 JS/CSS/字体等带哈希的构建产物,可进一步强化缓存效果:
- 将
js|css|woff2的映射值改为"1y",并加上immutable - 在对应 location 中用
add_header Cache-Control "public, immutable" always - 确保构建工具输出路径含哈希(如
app.a1b2c3.js),内容变则路径变,浏览器自然拉新
注意事项与避坑点
实际部署时容易忽略几个关键细节:
-
map不支持嵌套或复杂逻辑,后缀判断只能靠正则,避免写过于宽泛的模式(如~*\..*$)导致误匹配 -
expires指令只对 2xx/304 等成功响应生效,对 4xx/5xx 响应不添加头,这点无需额外处理 - 若同时用了
expires和add_header Cache-Control,前者会覆盖后者中的max-age,建议二者选其一;如需immutable,优先用add_header并加always - 修改 map 后必须重载 Nginx(
nginx -t && systemctl reload nginx),热更新不生效










