最近,我們在項目中實踐了webp圖檔,并且抽離出了工具子產品,整合到了項目的基礎模闆中。傳聞IOS10也将要支援webp,那麼使用webp帶來的性能提升将更加明顯。估計在不久的将來,webp會成為标配。
本文主要分享一下我們在webp圖檔使用上的實踐之路。
我們會從三部分來聊聊webp這個話題。
什麼是webp,它有什麼用?
使用webp的正常方法以及優劣。
我們是如何用上webp的。
PS:如果是對webp有一定了解的朋友,建議直接看第三部分。因為是講我們的實踐之路,是以第三部分會多講一些。
webp是谷歌推出的一種圖檔格式,它的優點就是同等畫面品質下,體積比jpg、png這些少了25%以上。
大家都知道移動網際網路時代,頁面大小和使用者留存息息相關,更快的加載頁面才能讓更多使用者關注到你的内容,而圖檔一直都是頁面體積的大頭,拿我們的活動頁面來說,圖檔占據了80%以上的頁面大小。是以使用webp的話,可以瞬間讓頁面大小下降1/4,不得不說是一個極具成本效益的優化點。
當然,它也不是沒有缺點,浏覽器對于webp的解碼速度相對于jpg來說會慢一些,不過這和體積減小帶來的性能提升,可以忽略不計了。
那麼既然webp這麼好,為什麼沒有大範圍使用呢?歸根結底還是webp是谷歌推出的,目前主流浏覽器隻有chrome和安卓支援。不過IOS也快支援了,期待ing^ ^。在caniuse上可以查到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格式,隻需要在圖檔路徑後面加上參數t=5即可得到webp格式的圖檔。
對于css引入的背景圖,我們存放在某個CDN上,這部分就麻煩了,不支援生成webp圖檔,是以隻能自己傳一份相應的webp圖檔上去。
而且由于各種原因和限制,我們無法采用上述說的伺服器端處理方案,是以隻能采用前端代碼處理的方式。我想有些公司沒使用webp可能也是這些原因,因為純前端處理确實挺繞的。
結合我們的業務情況,因為是營運活動頁,背景圖和商品圖基本各占一半,甚至背景圖更多,是以我們需要把css引入的圖檔和img标簽引入的圖檔都做webp相容T T。
針對img标簽引入的圖檔,由于我們的圖檔伺服器支援webp,而且我們的商品圖大多是懶加載,那麼就簡單了,直接修改我們的懶加載插件就可以實作,在替換真實圖檔路徑的時候判斷一下是否支援webp,然後替換相應的路徑就可以。
針對css引入的圖檔,我們采取的方案是利用css的優先級覆寫,比如說如果浏覽器支援webp,那麼我們給html根節點上加上webps的類名。這樣比如我們寫
的時候,再寫上
這樣,支援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前就加載,代碼的含義可以直接看注釋。
然後我們處理img标簽引入的圖檔,因為我們的圖檔伺服器支援webp,且用img引入的圖檔都是通過懶加載來載入的,是以這部分我們處理起來比較簡單,在懶加載替換真實路徑的時候,判斷cookie中是否存在webps=A這個cookie來決定加載的圖檔的url。
當然,如果你們不是懶加載的引入的圖檔,那麼可以在後端渲染的時候,通過我們寫入的cookie,來判斷是否使用webp圖檔,也很友善。這部分代碼比較簡單,就不貼出來了。
然後是css中引入的圖檔了,由于css不支援邏輯,我們現在能利用的就是html根節點的.webps的類名了。我們在SCSS中使用了這個mixin來加載圖檔。代碼作用可以看下注釋。
如果用的是less,可以通過下面這段代碼來實作同樣的功能。
最後就是如何生成webp圖檔了。對于css引入的圖檔,由于是放在CDN上,我們需要自己生成對應的webp圖檔。
如何做到開發的時候自動配套生成webp圖檔呢,開始我們想的是給我們的建構工具寫個插件來實作編譯時候生成webp圖檔,然而我們發現由于各個項目使用的建構工具可能不一樣,比如fis3、webpack還有我們自己開發建構工具的,太多了,針對每一個開發成本太高。是以我們決定用nodejs寫個小腳本,作用就是監控我們的圖檔檔案夾,随時生成配套的webp圖檔,當圖檔有增加、修改、删除時,它會相應的增加、修改、删除對應的webp圖檔。
工具代碼如下。預設監聽images檔案夾,npm install 安裝依賴之後,直接node webp-monitor.js既可。當然,前提是你按照好了第二部分所說的谷歌官方的webp生成工具,或者簡單的說你的終端需要有cwebp這個指令才行。
至此,我們便實作了在項目中使用webp圖檔。我們首先拿了一個活動頁試水,應該是明天會上線,上線後我把位址貼出來,http://m.zhuanzhuan.58.com/Mzhuanzhuan/zhuanzhuan/zzactivity/activity-xbl/大家可以看看效果如何,經測試圖檔确實小了很多呢。
文章中聊到的相關代碼都放到的github上,位址如下https://github.com/huangjiaxing/webp-monitor
感覺是一個比較民工的webp實踐方案,對于想使用webp但是卻不想和運維那些打交道的,可以嘗試下這個方案,還是挺不錯的^ ^。
轉載本站文章請注明作者和出處 哎呦大黃 – http://www.cnblogs.com/season-huang/ ,請勿用于任何商業用途