让网站根据浏览器是否支持 WebP 来自适应加载相应格式的图片,如果在代码中进行判断,那工作量是巨大的,因为要修改代码中每一个图片的引用方式,有没有一种简便高效的方法呢?答案还是有的,那就是修改 Nginx 的配置。
主要思路#
如何判断浏览器是否支持 WebP 格式的图片,除了在前端加载一个 1×1 像素的 WebP 图片来获取宽度的方法,还有个方法,那就是查看浏览器发出的请求头中的 Accept 字段,如果改字段中带着image/webp
说明浏览器支持 WebP,反之则就是不持支。
不支持 WebP 的 IE 的请求头 Accept 字段:
支持 WebP 的 Firefox 的请求头 Accept 字段:
支持 WebP 的 Chrome 的请求头 Accept 字段:
根据这个,我们可以修改 Nginx 的配置文件,让以 **.jgp
、.jpeg
和.png
结尾的请求 ** 并且请求头 Accept 字段包含image/webp
的请求进行 WebP 文件的判断,这个判断我们写在 Lua 文件中。在 Lua 文件中,先判断该文件对应的 WebP 文件是否存在,如果存在,则直接重定向到 WebP 文件,如果不存在,先调用 libwebp 方法生成 WebP 文件,再进行重定向。
有了这个思路,我们进行尝试。
修改准备#
Nginx 安装 Lua 模块#
略
服务器安装 libwebp#
参考:Nginx+Lua+libwebp 实现服务器图片自动转 WebP
Nginx.conf
#
因为 if 不能同时判断多个条件,所以我们定义一个变量,用 if 修改变量值,最后根据该变量的值来判断是否满足所有的条件。
location /img {
set $cwebp_flag 0;
if ($uri ~ \.(png|jpg|jpeg)$) {
set $cwebp_flag '${cwebp_flag}1';
}
if ($http_accept ~ image/webp) {
set $cwebp_flag '${cwebp_flag}1';
}
if ($cwebp_flag = 011) {
content_by_lua_file lua/imgProcess.lua;
}
}
imgProcess.lua
#
这个文件主要工作是:先判断该文件对应的 WebP 文件是否存在,如果存在,则直接重定向到 WebP 文件,如果不存在,先调用 libwebp 方法生成 WebP 文件,再进行重定向。
function file_exists(name)
local f=io.open(name,"r");
if f~=nil then io.close(f) return true else return false end
end
local originalFile = ngx.var.request_filename;
local newFile = ngx.var.request_filename .. ".webp";
if not file_exists(newFile) then
if not file_exists(originalFile) then
ngx.exit(404);
return;
end
os.execute("cwebp -q 75 " .. originalFile .. " -o " .. newFile);
if file_exists(newFile) then
ngx.header.vary = 'accept, accept-encoding';
ngx.header.x_webp = 'generate';
ngx.header.real_source_url = ngx.var.uri .. ".webp";
ngx.header.content_type = "image/webp";
return ngx.exec(ngx.var.uri .. ".webp");
else
ngx.exit(500);
return;
end
else
ngx.header.vary = 'accept, accept-encoding';
ngx.header.x_webp = 'read';
ngx.header.real_source_url = ngx.var.uri .. ".webp";
ngx.header.content_type = "image/webp";
return ngx.exec(ngx.var.uri .. ".webp");
end
测试#
用不支持 WebP 的 IE 和支持 WebP 的 Chrome 打开同一张图片的地址,我们发现服务器给他们返回的响应内容是不一样的。
支持 WebP 的 Chrome 的相应内容是 WebP 格式的图片:
而不支持 WebP 的 IE 的相应内容就是普通的 jpg 图片: