Nginx变量不直接生成Expires或Cache-Control,但可通过map预定义TTL并配合add_header动态注入;更推荐将版本号嵌入URL路径后用expires指令实现强缓存。

Nginx 的变量系统本身不直接生成 HTTP 响应头中的 Expires 或 Cache-Control: max-age,但可以通过内置变量(如 $time_iso8601、$date_gmt)配合 add_header 和 expires 指令,实现**基于时间逻辑的动态过期控制**——尤其适用于静态资源(JS/CSS/图片)需按版本、环境或请求时刻差异化缓存的场景。
用 expires 指令 + 变量间接实现“动态”过期
expires 指令不接受变量值(如 expires $my_custom_ttl 会报错),但它支持基于当前时间的相对偏移(expires 1h)或绝对时间(expires @23h30m)。真正能结合变量的是 add_header,可用于构造自定义 Cache-Control 或 Expires 值:
- 优先使用
expires:对整类静态资源统一设固定 max-age(如expires 1y),最高效、兼容性最好 - 需差异化时,用
add_header Cache-Control配合 map 构建条件变量:例如根据文件后缀、URI 路径或请求头决定 TTL - 避免在
location中重复写add_header;建议用map在 http 块预计算变量,再在响应中引用
通过 map + add_header 动态注入 Cache-Control
利用 map 将请求特征映射为 TTL 秒数,再拼接进 Cache-Control:
http {
# 根据 URI 后缀定义不同缓存时长(单位:秒)
map $sent_http_content_type $cache_ttl {
~*text/css 31536000; # 1年
~*application/javascript 31536000;
~*image/ 2592000; # 30天
default 3600; # 其他资源默认1小时
}
<pre class="brush:php;toolbar:false;">server {
location ~* \.(js|css|png|jpg|gif|ico)$ {
add_header Cache-Control "public, max-age=$cache_ttl";
# 同时可加 ETag(Nginx 默认开启)
etag on;
}
}}
注意:$sent_http_content_type 是响应头生成后的变量,确保在 add_header 中可用;map 必须定义在 http 块,且键值对末尾分号不能省略。
基于时间戳路径实现“自动失效”的伪动态策略
更可靠的做法是**让过期逻辑前置到 URL 层面**:将版本号或构建时间戳嵌入静态资源路径(如 /static/app.20240520.js),然后对所有带哈希/时间戳的路径启用强缓存:
location ~* ^/static/.*\.[0-9a-f]{8,}\.(js|css|png|jpg|gif)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}这样无需运行时计算变量,CDN 和浏览器都可长期缓存,发布新版本只需改文件名,旧资源自然失效。Nginx 变量在此仅用于日志记录或灰度判断,不参与缓存头生成。
慎用 $date_gmt 或 $time_iso8601 直接构造 Expires 头
虽然可以写 add_header Expires "$date_gmt";,但这只是当前时间,无法体现“过期时刻”。若真需绝对时间头,必须手动计算(如 GMT 时间 + N 秒),但 Nginx 不支持算术运算,只能靠外部模块(如 lua-nginx-module)或预生成配置。普通部署中不推荐此方式——既增加复杂度,又可能因服务器时钟漂移导致客户端解析错误。


















