1. 程式人生 > >移動 WEB 通用優化策略介紹(二)

移動 WEB 通用優化策略介紹(二)

提醒:本文最後更新於 843 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

算起來已經足足兩個半月沒有更新文章,這段時間過得比較忙:夜間跑步計劃、賣房買房以及工作上各種事情都湊到一塊了。實際上,最近也並沒有忙到完全抽不出時間寫部落格這種地步,根本原因可能還是變懶了,這樣不好。

幾個月前,我決定開始寫一系列有關「移動 WEB 通用優化」的文章,介紹「面向所有主流移動端瀏覽器(包括各種 APP 嵌入的通用 Webview)」的前端優化策略,本文是這個系列第二篇。

先來回顧下上篇文章最後的結論:

重要的 CSS、JS、JSON 資料直接內聯在 HTML 中,頭部禁止出現任何外鏈資源。同時,儘可能減少頁面傳輸體積。

採用了這個策略的頁面,理應能讓使用者在很短時間內看到主體內容,因為頭部 CSS 和 JS 都內聯了,不會阻塞瀏覽器渲染頁面。在我們的認識裡,瀏覽器會非同步載入頁面用到的圖片,載入圖片不會阻塞頁面渲染,更不會阻塞 JS 執行。實際情況是這樣嗎?

本文主要討論在移動 WEB 中,圖片的載入給頁面整體效能帶來的影響以及優化策略。

我們知道,瀏覽器的 DOMContentLoaded 事件會在主頁面載入並解析完成之後觸發,不會等頁面樣式、圖片、iframe 等子資源載入完。以下是 MDN 對它的描述:

The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

但在實際測試中,移動端完全相同的頁面,載入與不載入圖片對 DOMContentLoaded 觸發時機的影響卻很大。以下是我們在某個移動產品中,將圖片延遲載入後的 DOMContentLoaded 時間對比,可以看出明顯變化:

dom ready time

我們只是將頁面所有圖片(大約十幾張)進行延遲載入,就讓 DOMContentLoaded 事件提前 250 毫秒觸發。這是我之前沒有意料到的,移動裝置在網路、CPU、記憶體等方面的效能與 PC 相比差距很大,很多 PC 上可以忽略的問題,在移動端必須重視起來。

移動 WEB 要做好圖片優化,無外乎兩點:控制圖片大小控制圖片載入

控制圖片大小

圖片高寬越大,意味著需要越多的網路開銷。常見圖片格式都經過了高度壓縮,尺寸越大的圖片還意味著瀏覽器在解碼過程中需要耗費更多 CPU,解碼之後的點陣圖需要佔用更多記憶體。在移動端,我們更應該關注圖片大小。

根據 DPR(window.devicePixelRatio,裝置畫素比)選擇合適的圖片尺寸。現在的手機基本上都是高清屏,如果一味追求讓圖片更小而使用單倍圖也不現實。這一點上,最佳實踐是根據產品特性,結合使用者 DPR 分佈情況來選擇合適的尺寸。例如在我們某個產品中:圖片載入速度比圖片質量更重要;使用者 DPR 分佈前三是:2、3、1.5。我們最終使用了 1.5 倍圖,並且在圖床縮放圖片時,加了一點點銳化效果。最終圖片體積很小,質量也尚可接受。

處理好響應式圖片(Responsive Image)。移動上很多圖片寬度不是固定畫素值,例如通欄 Banner 圖片的寬度是跟著裝置走的。對於這種場景,使用 JS 獲取裝置寬度,拼出最適合當前裝置的圖片尺寸,交給圖床進行縮放,無疑能在圖片體積和質量上找到最佳平衡點。但這種做法並不可取,移動裝置寬度各式各樣,如果裁圖規格太多,容易降低 CDN 快取命中率。圖床實時處理完圖片再分發到 CDN 更耗時,在移動端讓圖片命中 CDN 快取也很重要。處理響應式圖片的最佳實踐是根據使用者螢幕尺寸分佈,制定出幾檔裁圖規則,頁面根據使用者裝置寬度使用最合適的檔位,並對重要的圖片(例如頭部焦點圖)提前預熱 CDN。

有一項名為 HTTP Client Hints 的技術,通過新增的 HTTP 請求頭部欄位,使得圖床可以優雅地返回最合適的圖片。目前這項技術在移動端尚未普及,詳情請檢視 HTTP Client Hints 介紹

使用 WEBP 格式。有一種減少圖片體積的靈丹妙藥 —— 使用壓縮比例更高的 WEBP 格式。《移動端圖片格式調研》這篇文章詳細地對比了各種移動端圖片格式及各自適用場景。對於 WEBP 的最佳實踐是隻要瀏覽器支援就用,雖然 WEBP 解碼慢於 JPG,但在同等圖片質量下,WEBP 體積通常比 JPG 小很多。

要判斷瀏覽器是否支援 WEBP,可以檢查 HTTP 請求頭部欄位 Accept 的值是否包含 webp。例如這是 Chrome 給圖片請求加的 Accept

Accept: image/webp,image/*,*/*;q=0.8

不是所有支援 WEBP 的瀏覽器都會這樣處理,可以針對這種情況使用特性檢測:

var webpImg = new Image;
webpImg.onload = function () {
    if(webpImg.width == 1){
        cookie('env_webp', 1); //cookie 方法需要自己實現
    }
};
webpImg.src = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAgA0JaQAA3AA/vv9UAA=';

這段示意程式碼的原理是:用 JS 載入 WEBP 圖片,如果能觸發 onload 並獲取到寬度,說明當前瀏覽器支援 WEBP。

控制圖片載入

我在《AMP,來自 Google 的移動頁面優化方案》一文中寫到:「將圖片、視訊等標籤和第三方功能換成 AMP Components 後,AMP Runtime 可以自動處理延遲載入、按需載入等邏輯,確保頁面首屏效能」。在移動瀏覽器開啟網頁,經常能感覺到明顯的卡頓。造成卡頓的原因除了頁面 DOM 結構複雜、CSS 過多地觸發 Layout/Paint/Composite、存在複雜 JS 邏輯等等,也可能是沒有控制圖片的載入時機。

通常瀏覽器會併發載入 6 個同域名圖片,如果做了域名雜湊,那很可能在開啟頁面後的短短几秒內,幾十個圖片都在載入。這些連線帶來的 TCP、頻寬、CPU、記憶體等開銷,很容易讓頁面卡頓。所以在移動端,我們要讓圖片載入變得可控。

按需載入圖片。在 PC 端,我們基本都會做圖片 Lazy Load,這個優化策略在移動端同樣適用。由於移動端效能有限、頻寬昂貴,Lazy Load 更為重要。實際上不光是圖片可以做 Lazy Load,頁面所有資源包括 DOM 節點都應該做成按需載入。通常在移動端,我們只加載頁面可視區域及其下方一定距離內的資源。

順序載入圖片。在 PC 端,由於硬體效能和頻寬足夠,並行載入更多的圖片通常是最好的選擇。而在移動端,人為控制圖片載入順序,例如使其從上到下、從左到右逐個載入,有時可以帶來更好的體驗。

不要在頁面滾定時載入圖片。按需載入圖片邏輯需要監聽頁面滾動事件,根據頁面當前可視區域決定載入哪些圖片。在移動端滾動頁面本來就很耗費效能,如果這時候還要載入圖片,非常容易造成頁面卡頓。在頁面滾定停止之後才開始載入圖片,能有效減少這種卡頓。

好了,本文先就寫這麼多。還是老規矩,有任何問題和疑問歡迎留言討論。Disqus 最近在國內經常無法載入,怎麼處理你們都懂的。實在不行也可以給我發郵件,本站「關於」頁面有我的郵箱。

--EOF--

提醒:本文最後更新於 843 天前,文中所描述的資訊可能已發生改變,請謹慎使用。