一、什麼是webp,它有什麼用?
WebP(發音:weppy)是一種同時提供了有損壓縮與無損壓縮(可逆壓縮)的圖片文件格式,派生自影像編碼格式VP8,被認為是WebM多媒體格式的姊妹項目,是由Google在購買On2 Technologies後發展出來,以BSD授權條款發布。
WebP支持的像素最大數量是16383×16383。有損壓縮的WebP僅支持8-bit的YUV 4:2:0格式。而無損壓縮(可逆壓縮)的WebP支持VP8L編碼與8-bit之ARGB色彩空間。又無論是有損或無損壓縮皆支持Alpha透明通道、ICC色彩配置、XMP詮釋數據。
WebP有靜態與動態兩種模式。動態WebP(Animated WebP)支持有損與無損壓縮、ICC色彩配置、XMP詮釋數據、Alpha透明通道。
webp是谷歌推出的一種圖片格式,它的優點就是同等畫面質量下,體積比jpg、png這些少了25%以上。
大家都知道移動互聯網時代,頁面大小和用戶留存息息相關,更快的載入頁面才能讓更多用戶關注到你的內容,而圖片一直都是頁面體積的大頭,拿我們的活動頁面來說,圖片佔據了80%以上的頁面大小。所以使用webp的話,可以瞬間讓頁面大小下降1/4,不得不說是一個極具性價比的優化點。
當然,它也不是沒有缺點,瀏覽器對於webp的解碼速度相對於jpg來說會慢一些,不過這和體積減小帶來的性能提升,可以忽略不計了。
那麼既然webp這麼好,為什麼沒有大範圍使用呢?歸根結底還是webp是谷歌推出的,目前主流瀏覽器只有chrome和安卓支持。不過IOS也快支持了,期待ing^ ^。在caniuse上可以查到webp目前的兼容性。
二、使用webp的常規方法以及它們的優劣
首先,我們需要一個工具把圖片轉成webp格式,這裡就使用google的官方工具即可,鏈接。
這個裝好之後,你的控制台就有了一個cwebp命令。運行cwebp -h,成功顯示幫助信息就表示安裝好了。
通過這個工具就可以生成webp圖片了,有了webp圖片之後,之後便是如何使用了,常見有兩種方案。
方案一:伺服器端處理
這是最最最省心的方法了,支持webp圖片的瀏覽器在向伺服器發送請求時,會在請求頭Accept中帶上image/webp。然後伺服器就可以根據是否含有這個頭信息來決定是否返回webp圖片了。
這個方法只需要在web伺服器那裡做一些操作即可,十分簡單方便。
不過這個方案缺點也很明顯,首先通過請求頭檢測,某些設備可能不太准。其次,現在圖片等靜態資源都會放到CDN伺服器上,那麼在這個層面加上判斷webp的邏輯就有點麻煩了。
方案二:前端檢測是否支持webp然後再請求相應格式的圖片
這個方法好處是十分穩妥,通過特性檢查可以知道用戶的瀏覽器是否支持webp,壞處就是需要在業務代碼中加入檢測webp的邏輯。
通常做法是在頁面載入前先執行一段webp的檢測,得出瀏覽器是否支持webp格式,把結果存入cookie中,在載入圖片時,如果是懶載入的圖片,那麼根據是否支持webp來處理圖片路徑就好,如果不是懶載入的圖片,可以在後端渲染模板時,根據我們設置好的是否支持webp的cookie來判斷。
目前這些都是針對頁面通過img標籤引入圖片時兼容webp的方式。如果是css中引入的圖片,方案一般就是構建兩套css,然後在後端模板中根據cookie判斷使用哪一套,或是在css中通過選擇器覆蓋,比如對於支持webp的瀏覽器,我們在html根節點上加上webps的類名,然後針對引入的圖片,通過這個類名做選擇器優先順序覆蓋,具體的我們在第三部分看著代碼細說。
三、我們是如何用上webp的
重點來了,下面來說說我們對webp的實戰。
首先說說我們這邊現狀吧,我們的圖片有兩種存放方式。對於一些動態圖片,比如商品圖,這些是存放在我們的圖片伺服器上,這個伺服器支持webp格式,只需要在圖片路徑後面加上參數t=5即可得到webp格式的圖片。
對於css引入的背景圖,我們存放在某個CDN上,這部分就麻煩了,不支持生成webp圖片,所以只能自己傳一份相應的webp圖片上去。
而且由於各種原因和限制,我們無法採用上述說的伺服器端處理方案,所以只能採用前端代碼處理的方式。我想有些公司沒使用webp可能也是這些原因,因為純前端處理確實挺繞的。
結合我們的業務情況,因為是運營活動頁,背景圖和商品圖基本各佔一半,甚至背景圖更多,所以我們需要把css引入的圖片和img標籤引入的圖片都做webp兼容T T。
針對img標籤引入的圖片,由於我們的圖片伺服器支持webp,而且我們的商品圖大多是懶載入,那麼就簡單了,直接修改我們的懶載入插件就可以實現,在替換真實圖片路徑的時候判斷一下是否支持webp,然後替換相應的路徑就可以。
針對css引入的圖片,我們採取的方案是利用css的優先順序覆蓋,比如說如果瀏覽器支持webp,那麼我們給html根節點上加上webps的類名。這樣比如我們寫
span{background-image:url(a.jpg)}
的時候,再寫上
.webps span{background-image:url(a.jpg.webp)}
這樣,支持webp格式的設備就會自動載入webp的圖片了。
當然這裡你肯定會有兩個疑問
一是每次寫代碼的時候加上.webps再寫一遍工作量也太大了。
二是每張圖對應的webp圖片是哪裡來的?需要自己生成嗎?
針對這兩個問題,我們找到了相應的解決方法,對於問題一我們使用css預處理器做到了生成對應的webp的代碼。
問題二我們使用nodejs寫了一個腳本來監控圖片文件夾,當圖片增加、修改、刪除時,它便會生成或刪除對應的webp圖片。
說了這麼多,我們一起來看一看代碼實現吧。
首先,我們需要在頁面最開始的部分加入一段webp的檢查代碼。這段代碼的作用就是檢查當前瀏覽器是否支持webp,如果支持,那麼給html根節點加上webps的類名,以供css使用。並且在cookie中記錄一個名為webps,值為A的cookie,為期一年。這樣,之後就可以在css中使用webp類名做兼容處理,img標籤引入的圖片也可以通過cookie得知瀏覽器是否支持webp,然後做相應處理,後端也可以通過cookie得知設備對webp的支持情況來做一些差別渲染。
這段代碼如下,需要注意的是這段代碼要在引入css前就載入,代碼的含義可以直接看注釋。
(function(doc) { // 給html根節點加上webps類名 function addRootTag() { doc.documentElement.className += " webps"; } // 判斷是否有webps=A這個cookie if (!/(^|;\s?)webps=A/.test(document.cookie)) { var image = new Image(); // 圖片載入完成時候的操作 image.onload = function() { // 圖片載入成功且寬度為1,那麼就代表支持webp了,因為這張base64圖是webp格式。如果不支持會觸發image.error方法 if (image.width == 1) { // html根節點添加class,並且埋入cookie addRootTag(); document.cookie = "webps=A; max-age=31536000; domain=58.com"; } }; // 一張支持alpha透明度的webp的圖片,使用base64編碼 image.src = 'data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA=='; } else { addRootTag(); } }(document));
然後我們處理img標籤引入的圖片,因為我們的圖片伺服器支持webp,且用img引入的圖片都是通過懶載入來載入的,所以這部分我們處理起來比較簡單,在懶載入替換真實路徑的時候,判斷cookie中是否存在webps=A這個cookie來決定載入的圖片的url。
當然,如果你們不是懶載入的引入的圖片,那麼可以在後端渲染的時候,通過我們寫入的cookie,來判斷是否使用webp圖片,也很方便。這部分代碼比較簡單,就不貼出來了。
然後是css中引入的圖片了,由於css不支持邏輯,我們現在能利用的就是html根節點的.webps的類名了。我們在SCSS中使用了這個mixin來載入圖片。代碼作用可以看下注釋。
/* 通過這個函數來引入圖片,例如: #wrapper{ @include bg('../img/sample.jpg') } 這段代碼經過編譯後便會生成如下兩句代碼 #wrapper{ background-image:url('../img/sample.jpg'); } .webp #wrapper{ background-image:url('../img/sample.jpg.webp'); } */ @mixin bg($url) { background-image: url($url); @at-root(with: all) .webps & { background-image: url($url + '.webp'); } }
如果用的是less,可以通過下面這段代碼來實現同樣的功能。
.mixin(@url) { background-image: url(@url); .webps & { background-image: url('@{url}.webp'); } }
最後就是如何生成webp圖片了。對於css引入的圖片,由於是放在CDN上,我們需要自己生成對應的webp圖片。
如何做到開發的時候自動配套生成webp圖片呢,開始我們想的是給我們的構建工具寫個插件來實現編譯時候生成webp圖片,然而我們發現由於各個項目使用的構建工具可能不一樣,比如fis3、webpack還有我們自己開發構建工具的,太多了,針對每一個開發成本太高。所以我們決定用nodejs寫個小腳本,作用就是監控我們的圖片文件夾,隨時生成配套的webp圖片,當圖片有增加、修改、刪除時,它會相應的增加、修改、刪除對應的webp圖片。
工具代碼如下。默認監聽images文件夾,npm install 安裝依賴之後,直接node webp-monitor.js既可。當然,前提是你按照好了第二部分所說的谷歌官方的webp生成工具,或者簡單的說你的終端需要有cwebp這個命令才行。
/* webp圖片生成 運行:npm install && npm start 程序依賴谷歌官方webp轉換工具cwebp mac下安裝 brew install webp windows下可以去google官方下載 安裝完成後運行cwebp -h 如果顯示了使用幫助則表示安裝成功 */ const process = require('child_process'); const fs = require('fs'); const chokidar = require('chokidar'); const log = console.log.bind(console); const ignoreFiles = /(^\..+)|(.+[\/\\]\..+)|(.+?\.webp$)/; // 忽略文件.開頭和.webp結尾的 let quality = 75; // webp圖片質量,默認75 let imgDir = 'images'; // 默認圖片文件夾 // 得到對應的webp格式的文件名,默認為文件名後加上.webp function getWebpImgName(path) { return `${path}.webp`; } // 得到shell命令 function getShellCmd(path) { return `cwebp -q ${quality} ${path} -o ${getWebpImgName(path)}`; } // 監控文件夾 var watcher = chokidar.watch(imgDir, { ignored: path => { return ignoreFiles.test(path); }, persistent: true // 保持監聽狀態 }); // 監聽增加,修改,刪除文件的事件 watcher.on('all', (event, path) => { switch (event) { case 'add': case 'change': generateWebpImg(path, (status) => { log('生成圖片' + getWebpImgName(path) + status); }); break; case 'unlink': deleteWebpImg(getWebpImgName(path), (status) => { log('刪除圖片' + getWebpImgName(path) + status); }); break; default: break; } }); log('biubiubiu~~~ 監控已經啟動'); function generateWebpImg(path, cb) { process.exec(getShellCmd(path), err => { if (err !== null) { cb('失敗'); log('請先運行cwebp -h命令檢查cwebp是否安裝ok。') log(err); } else { cb('成功'); } }); } function deleteWebpImg(path, cb) { fs.unlink(path, (err) => { if (err) { cb('失敗'); log(err) } else { cb('成功'); }; }); }
到此這篇關於webp格式圖片介紹及用法總結的文章就介紹到這了,更多相關webp圖片格式內容請搜索以前的文章或繼續瀏覽下面的相關文章,希望大家以後多多支持!
原創文章,作者:簡單一點,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/172225.html