这一篇仅讨论在同时存在原始图片版本和webp版本的情况下,如何使Nginx尝试去返回webp版本给前端(比如浏览器支持webp的话),并且在不存在webp版本图片或不支持webp时回退成原始版本传递。
这种方式,主要是可以在不动目前网页代码功能上,实现自适应webp支持。
首先就是你的原始图片和webp版本(原始图片含扩展名的情况下,添加webp扩展名)在一起的情况下,直接就是代码如下。
在nginx.conf的http块中:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
在你的vhost中,增加:
location ~* ^/.+\.(png|jpg|jpeg)$ {
more_set_headers "Vary: Accept";
more_set_headers "Cache-Control: public, no-transform, max-age=2592000";
try_files $uri$webp_suffix $uri =404;
}
这样在访问jpg、jpeg、png图时,nginx就会尝试访问webp版本,不存在时会自动降级返回。
相当于是浏览器支持时,访问的是原始图片完整名.webp,不支持时,直接就是原始图片完整名。
如果你像我一样,webp文件单独一个目录放(不污染原始目录),且只想对wordpress的uploads进行webp转换,那么可以试试以下方式。我是在wp-content新建webp目录,里面结构与uploads一致且存放为webp版本图片。
大家可以按照自己的实际来修改。
location ~* ^/wp-content/uploads/(.+\.(png|jpg|jpeg))$ {
more_set_headers "Vary: Accept";
more_set_headers "Cache-Control: public, no-transform, max-age=2592000";
if ($http_accept ~* "webp") {
rewrite ^/wp-content/uploads/(.*)$ /wp-content/webp/$1.webp last;
}
try_files $uri =404;
}
location ~* ^/wp-content/webp/(.+\.webp)$ {
more_set_headers "Vary: Accept";
more_set_headers "Cache-Control: public, no-transform, max-age=2592000";
try_files $uri @fallback_to_original;
}
location @fallback_to_original {
more_set_headers "Vary: Accept";
more_set_headers "Cache-Control: public, no-transform, max-age=2592000";
rewrite ^/wp-content/webp/(.*)\.webp$ /wp-content/uploads/$1 break;
try_files $uri =404;
}
可能有朋友稍微懂一些的,会觉得是不是代码实现有点复杂了。但这是最好的结果,虽然单个location也能实现这个功能(包括AI也只会写一个location给你,我进行了测试),但实际上,当你的文件含非英文字符,比如中文字符,那么就会被转义,转义后,硬盘上是不存在这个文件的(除非你一开始存储就是以转义方式存储),那么Nginx就回退到原始文件,也就是含非英文字符的无法享受到webp返回。而现在这种略显复杂的实现方式,通过内部重定向逻辑来解决字符编码的问题。效率上,实际上对于Nginx几乎无影响。
另外建议大家在全局中启用open_file_cache,代码如下。这样nginx可以缓存到是否存在文件在内存中,而不用每次去硬盘查询。
还是在nginx.conf的http块中:
open_file_cache max=100000 inactive=30s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
转载请注明转自: kn007的个人博客 的《Nginx尝试返回webp版本的图片给浏览器》
