Nginx 实现“访问原图 URL 自动返回 WebP 缩略图”的核心是:检测 Accept 头支持 WebP、用 try_files 优先查找已生成的 .webp 缩略图、不存在则代理至后端服务生成,并通过 Vary Accept 确保缓存正确。

在 Nginx 中实现“访问原图 URL 时自动返回对应 WebP 格式缩略图”,关键不在于重写 URL 路径,而在于:检测请求是否支持 WebP、检查缩略图是否存在、按需生成(或代理)WebP 缩略图,并正确设置响应头。这通常需要结合 try_files、map、location 匹配和后端处理(如 ImageMagick + CGI / Lua / 或独立缩略图服务)来完成。纯 Nginx 无法直接转换图片,但可智能路由与缓存。
1. 判断客户端是否支持 WebP(通过 Accept 头)
先用 map 指令提取请求头中的 WebP 支持信号,为后续逻辑提供变量:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}该配置定义了变量 $webp_suffix:当请求头 Accept: image/webp(或含 webp)时值为 .webp,否则为空。注意大小写不敏感匹配。
2. 匹配图片路径并尝试命中 WebP 缩略图文件
假设原始大图路径为 /images/photo.jpg,对应 WebP 缩略图约定存于 /thumbs/photo.jpg.webp(或统一后缀 /thumbs/photo.webp)。用 location 捕获图片请求,并用 try_files 优先查找已生成的 WebP 缩略图:
location ~ ^/images/(.+)\.(jpe?g|png|gif)$ {
# 构建缩略图路径(例如:/thumbs/photo.jpg.webp)
set $thumb_path "/thumbs/$1.$2$webp_suffix";
<pre class="brush:php;toolbar:false;"># 先尝试返回已存在的 WebP 缩略图
try_files $thumb_path @generate_webp;}
如果 /thumbs/photo.jpg.webp 存在且客户端支持 WebP,Nginx 直接返回;否则跳转到 @generate_webp 处理段。
3. 动态生成或代理生成 WebP 缩略图(推荐方案)
纯 Nginx 不支持图像处理,所以需交由外部服务。两种主流做法:
-
用 Lua + OpenResty 调用 imagemagick 或 cwebp:适合中小流量,需安装
ngx_http_lua_module和命令行工具。Lua 脚本读取原图、缩放、转 WebP、写入缓存目录、再返回。 - 反向代理到专用缩略图服务(更推荐):例如使用 weserv/images、sharp(Node.js) 或自研 Go/Python 服务。Nginx 仅做路由与缓存:
location @generate_webp {
# 将请求改写为缩略图服务能理解的格式,例如:
# 原请求:/images/photo.jpg → 转给 http://thumb-svc/thumb?src=/images/photo.jpg&w=400&f=webp
proxy_pass https://thumb-svc/thumb?src=$request_uri&w=400&f=webp;
proxy_cache thumb_cache;
proxy_cache_valid 200 7d;
add_header Vary Accept;
}注意:add_header Vary Accept 确保 CDN 或 Nginx 自身缓存能区分 WebP / 非 WebP 请求,避免内容错乱。
4. 回退逻辑:不支持 WebP 时返回原图(保持兼容)
上面的 try_files 只处理了 WebP 分支。若需对非 WebP 客户端也返回缩略图(如 JPEG),可扩展为双路径 fallback:
location ~ ^/images/(.+)\.(jpe?g|png|gif)$ {
set $thumb_webp "/thumbs/$1.$2.webp";
set $thumb_jpg "/thumbs/$1.$2";
<pre class="brush:php;toolbar:false;"># 优先找 .webp(仅当 Accept 含 webp),否则找同名缩略图(如 .jpg)
try_files $thumb_webp $thumb_jpg =404;}
前提是你的缩略图目录中已预生成好 .jpg 和 .webp 两种版本——适合静态资源构建场景(如 CI 流程批量生成)。
不复杂但容易忽略的是缓存控制与 Vary 头。只要路径、参数、Accept 头三者一致,就应命中同一份缓存;否则可能返回错误格式或 404。实际部署前务必用 curl -H "Accept: image/webp" 和不带该头的请求交叉验证响应与状态码。


















