讓網站根據瀏覽器是否支援 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 圖片: