nginx可通过map指令基于.webp后缀或accept头动态设置cache-control:静态webp用map $sent_http_content_type匹配后缀设长缓存,内容协商则需联合$http_accept与$sent_http_content_type判断响应类型再差异化配置。

要让Nginx对WebP图片单独设置Cache-Control头(比如比普通图片更长的缓存时间),关键不是“识别WebP格式再改响应头”,而是利用Nginx的map指令根据请求URI或Accept头动态区分WebP资源,再结合expires或add_header实现差异化缓存策略。
确认WebP资源如何被服务
WebP图片通常有两种提供方式,配置逻辑不同:
-
静态文件直接提供:如
/images/photo.webp,此时靠文件后缀识别 -
通过内容协商动态提供:客户端带
Accept: image/webp,服务端返回WebP(但URL仍是.jpg),此时需检查请求头
多数场景推荐第一种(显式.webp路径),更可控、易调试。若用第二种,需配合try_files和map判断是否命中WebP变体。
基于文件后缀的独立缓存配置
在http块中定义变量,匹配.webp后缀并设置缓存时长:
map $sent_http_content_type $webp_cache_time {
~*image/webp "1y";
default "1d";
}然后在server或location中应用:
location ~* \.(webp|jpe?g|png|gif)$ {
expires $webp_cache_time;
# 或用 add_header(注意:expires会覆盖Cache-Control,二者选其一)
# add_header Cache-Control "public, max-age=31536000" always;
}⚠️ 注意:expires指令会自动设置Cache-Control和Expires头;若需精细控制(如加immutable),改用add_header Cache-Control ... always,并确保always参数生效(避免被子请求覆盖)。
基于Accept头的内容协商缓存(进阶)
当WebP通过Accept协商返回(URL不变),需先判断是否实际返回了WebP内容:
map $http_accept $webp_requested {
~*webp 1;
default 0;
}
<p>map $sent_http_content_type $is_webp_response {
~*image/webp 1;
default 0;
}</p><p>map $is_webp_response $webp_cache_maxage {
1 "31536000";
0 "86400";
}</p>再在图片location中使用:
location ~* \.(jpe?g|png|gif)$ {
add_header Cache-Control "public, max-age=$webp_cache_maxage, immutable" always;
# 后续try_files或proxy_pass需确保真实返回的是WebP(例如有.webp同名文件优先)
}该方式依赖后端(或Nginx自身)正确返回WebP内容,否则$sent_http_content_type不匹配,缓存策略失效。
验证与调试要点
配置后务必验证实际响应头:
- 用
curl -I https://yoursite.com/photo.webp检查Cache-Control值 - 对比
.jpg和.webp同名资源的缓存头是否不同 - 若用内容协商,加
-H "Accept: image/webp"测试是否触发WebP分支及对应缓存 - Nginx日志中可加入
$webp_cache_maxage变量辅助排查
不复杂但容易忽略:确保map定义在http块顶层,且变量名不冲突;add_header ... always中的always不能省略,否则304响应不会携带该头。











