前端效能優化之路——圖片篇。
本人是一名前端開發者,在公司負責目前負責資訊流服務,為五大手機廠商和各大App提供服務,每天的請求就是以億計算,加上我們又做了SSP和DSP,就是類似於百度廣告聯盟,騰訊廣點通這種。接觸過的應該知道,所以前端優化一直是我頭痛的問題,不僅要注重使用者體驗,同時要兼顧收益,有時候必須犧牲一些使用者體驗,但是作為一名有思想的前端,還是努力規避掉,希望能和從事相同業務的同學一起學習交流一下,話不多說,就來分享我的效能優化之路,有什麼不對的知識點,麻煩大家指出批評。
- 先附上基本的yahoo軍規——yahoo前端效能團隊總結的35條黃金定律
- web前端優化之圖片優化
Media Queries 呼叫高清背景圖
國內手機發展迅速,用 retina顯示屏的越來越多,假如現在有一張圖片,有兩部手機,一部是普通顯示屏,一部是高清顯示屏,在同樣大小的螢幕上,高清顯示屏中的點陣圖會被放大,圖片會變得模糊。
通過 devicePixelRatio的值,就可以區分普通顯示屏和高清屏,當devicePixelRatio值等於1時(也就是最小值),那麼它普通顯示屏,當devicePixelRatio值大於1(通常是1.5、2.0),那麼它就是高清顯示屏。這時候我們可以讓UI準備2套圖片,甚至是3套圖片,不同畫素的圖利用媒體查詢結合 devicePixelRatio 可以區分普通顯示屏和高清顯示屏,並給出瞭如下CSS設計方案:
.css{/* 普通顯示屏(裝置畫素比例小於等於1.3)使用1倍的圖 */
background-image: url(img_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:1.5){
.css{/* 高清顯示屏(裝置畫素比例大於等於1.5)使用2倍圖 */
background-image: url(img_2x.png);
}
}
也可以用less或者sass
bg-image($url)
background-image: url($url + "@2x.png")
@media (-webkit -min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
background-image: url($url + "@3x.png")
如果省時間通用性高,就像我們是服務端用nginx對圖片進行處理,想要什麼樣尺寸的圖片自己裁切,我們提供了按比例縮放和自定尺寸的裁切方法,地址後拼接字串就行。
http://image.uczzd.cn/12046251381056834816.jpg?id=0&from=export&width=800&height=600
- 使用更小更快更強,新一代圖片格式 WebP
WebP是谷歌在10年推出一種新型圖片格式,最早也是應用在谷歌產品中,谷歌釋出的Android Studio 2.3正式版中就包括對WebP支援的更新,在實測中,webp 格式比 jpg 格式減小約 20%。這對優化使用者體驗,減少CDN頻寬消耗有很好的效果,但並不是所有瀏覽器都支援 webp ,所以為了使用 webp,需要做一點相容性的工作。
與其他圖片格式相比,在肉眼無法分辨圖片質量差異的情況下,WebP的空間佔用是最小的,目前國內外各大網際網路公司都已經開始應用這一圖片格式。比如美團
在識別階段,我們有兩種方法:
1. Server 處理
- 通過 UAString 判斷瀏覽器支援情況
只要有請求,服務端就能拿到你的User-Agent資訊,通過對瀏覽器進行分類,支援webp放在白名單裡,不支援的則為黑名單。判斷為白名單,則直接呼叫,返回webp格式圖片;反之,則顯示原圖。這種方式的優點在於,只需定期維護白名單即可,邏輯簡單;缺點則在於不可擴充套件、不可測試、UA判斷會出現不準確的情況。
- 讀取 JavaScript 種下的 cookie 判斷瀏覽器支援情況
Server處理中的另一種方式是通過讀取 JavaScript 種下的 cookie來實現判斷。這種方式的優點是表現穩定,訪問速度更快,切換無壓力。但缺點是,頁面靜態化會導致使用者切換瀏覽器時不能自主更新,圖片服務失效。比如使用者用支援webp的瀏覽器A請求頁面,這時快取的靜態頁面均使用webp圖片,但當該使用者使用不支援webp的瀏覽器B時,訪問網頁則會出現請求不到圖片的報錯。
- Client 處理
Client 處理,是美團云為美團主站提供的處理方式。在這種處理方式中,瀏覽器端傳送的beacon webp 請求後,通過檢測其載入情況來判定 webp 支援情況,然後瀏覽器寫一個cookie。之後通過讀取瀏覽器cookie判斷是否支援webp,就可以進行下一步替換操作了。
2.替換圖片過程中也是有兩種處理方式:
- Server 處理
在 server 端處理的優點是對下游開發者透明,缺點是靜態頁面的快取數量會翻倍。
替換方式如下:
- 生成 URL 的函式( 比如 $deal->getImageUrl ) ,通過執行函式中直接實現替換
對 varnish 靜態化的頁面,首先識別瀏覽器請求頭型別,然後將webp 和傳統 jpg 的各快取一份兩份待處理。然後在生成 URL 的地方做替換。
- Client 處理
在 client 端處理可以比較好地應對頁面靜態化的情況,主要針對懶載入(非首屏)的圖片進行處理,直接通過修改懶載入器來實現。
對非懶載入的圖片暫時沒有特別好的辦法。目前,可用替換路徑的方式來處理。
Client 處理實際上效果也是不錯的,美團頁面裡90%以上的圖片都是懶載入的,基本上都可以滿足需求。對於大多數使用者來說,採用Client 處理實現webp轉換是個不錯的選擇。
- tracking Pixel(畫素追蹤)精準追蹤資料
既然提到圖片這一塊,我有忍不住想扯寫些題外的tracking Pixel(畫素追蹤),幾乎所有網站都會做資料的採集,上報統計。特別是我們做SSP、DSP廣告這塊需要獲取例如
- 使用者使用的瀏覽器、作業系統、解析度等。
- 使用者瀏覽行為記錄,比如使用者網站上的點選行為、購買行為等。
- 使用者在APP、WEB中停留時間、是否活躍等
資料永遠說的是實話,資料證明一切可能。如facebook廣告投放的跨境電商朋友都會使用facebook Pixel(畫素追蹤)以獲得各環節的精準資料。這樣追蹤資料後,我們才能投放廣告後銷量上去了,哪個才是效果最好的,哪個效果不好,進而通過多個數據對比,對廣告進行合理的調整優化。
國內搜狗、百度、360、新浪都是用這種tracking Pixel方法,實際就是利用1px 的圖片,在圖片地址字尾拼接你需要的資訊引數,瀏覽器在請求任何資源的時候會發送當前系統的資料,比如瀏覽器資訊,作業系統資訊,作為http請求頭送過去,他們就能統計了。
為什麼不用js請求統計?
並不是所有的頁面都支援JS的!NoJSStats的實現機制就是網站分析中點選流資料獲取的方式之一——Web Beacons,即在頁面中嵌入一個1畫素的透明圖片,當該頁面被瀏覽時,圖片就會被請求載入,於是在後端的伺服器日誌中就會記錄該圖片的請求日誌,這樣就可以獲得日誌記錄。
例如百度:
這是百度1px圖片地址: http://wn.pos.baidu.com/adx.php?
var url = ["//eclick.baidu.com/se.jpg?", "type=fatalError", "data=1220", "mes=" + encodeURIComponent(e)].join("&"),
img = new Image;
img.src = url
百度在位址列後拼接了很多引數,後端按照圖片字尾名生成對應的資料報表。
本文引用@美團雲 提供的webP方法,感謝。