让网站根据浏览器是否支持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 实现服务器图片自动转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图片: