1. 程式人生 > >H5首屏秒開方案

H5首屏秒開方案

隨著移動裝置效能不斷增強,web 頁面的效能體驗逐漸變得可以接受,又因為 web 開發模式的諸多好處(跨平臺,動態更新,減體積,無限擴充套件),APP 客戶端裡出現越來越多內嵌 web 頁面(為了配上當前流行的說法,以下把所有網頁都稱為 H5 頁面,雖然可能跟 H5 沒關係),很多 APP 把一些功能模組改成用 H5 實現。

雖然說 H5 頁面效能變好了,但如果沒針對性地做一些優化,體驗還是很糟糕的,主要兩部分體驗:

1.頁面啟動白屏時間:開啟一個 H5 頁面需要做一系列處理,會有一段白屏時間,體驗糟糕。

2.響應流暢度:由於 webkit 的渲染機制,單執行緒,歷史包袱等原因,頁面重新整理/互動的效能體驗不如原生。

本文先不討論第二點,只討論第一點,怎樣減少白屏時間。對 APP 裡的一些使用 H5 實現的功能模組,怎樣加快它們的啟動速度,讓它們啟動的體驗接近原生。

過程

為什麼開啟一個 H5 頁面會有一長段白屏時間?因為它做了很多事情,大概是:

初始化 webview -> 請求頁面 -> 下載資料 -> 解析HTML -> 請求 js/css 資源 -> dom 渲染 -> 解析 JS 執行 -> JS 請求資料 -> 解析渲染 -> 下載渲染圖片

一些簡單的頁面可能沒有 JS 請求資料 這一步,但大部分功能模組應該是有的,根據當前使用者資訊,JS 向後臺請求相關資料再渲染,是常規開發方式。

一般頁面在 dom 渲染後能顯示雛形,在這之前使用者看到的都是白屏,等到下載渲染圖片後整個頁面才完整顯示,首屏秒開優化就是要減少這個過程的耗時。

前端優化

上述開啟一個頁面的過程有很多優化點,包括前端和客戶端,常規的前端和後端的效能優化在 PC 時代已經有最佳實踐,主要的是:

1.降低請求量:合併資源,減少 HTTP 請求數,minify / gzip 壓縮,webP,lazyLoad。

2.加快請求速度:預解析DNS,減少域名數,並行載入,CDN 分發。

3.快取:HTTP 協議快取請求,離線快取 manifest,離線資料快取localStorage。

4.渲染:JS/CSS優化,載入順序,服務端渲染,pipeline。

其中對首屏啟動速度影響最大的就是網路請求,所以優化的重點就是快取,這裡著重說一下前端對請求的快取策略。我們再細分一下,分成 HTML 的快取,JS/CSS/image 資源的快取,以及 json 資料的快取。


HTML 和 JS/CSS/image 資源都屬於靜態檔案,HTTP 本身提供了快取協議,瀏覽器實現了這些協議,可以做到靜態檔案的快取。

總的來說,就是兩種快取:

1.詢問是否有更新:根據 If-Modified-Since / ETag 等協議向後端請求詢問是否有更新,沒有更新返回304,瀏覽器使用本地快取。

2.直接使用本地快取:根據協議裡的 Cache-Control / Expires 欄位去確定多長時間內可以不去發請求詢問更新,直接使用本地快取。


前端能做的最大限度的快取策略是:HTML 檔案每次都向伺服器詢問是否有更新,JS/CSS/Image資原始檔則不請求更新,直接使用本地快取。那 JS/CSS 資原始檔如何更新?常見做法是在在構建過程中給每個資原始檔一個版本號或hash值,若資原始檔有更新,版本號和 hash 值變化,這個資源請求的 URL 就變化了,同時對應的 HTML 頁面更新,變成請求新的資源URL,資源也就更新了。

前端能做的最大限度的快取策略是:HTML 檔案每次都向伺服器詢問是否有更新,JS/CSS/Image資原始檔則不請求更新,直接使用本地快取。那 JS/CSS 資原始檔如何更新?常見做法是在在構建過程中給每個資原始檔一個版本號或hash值,若資原始檔有更新,版本號和 hash 值變化,這個資源請求的 URL 就變化了,同時對應的 HTML 頁面更新,變成請求新的資源URL,資源也就更新了。
這些快取策略可以實現 JS/CSS 等資原始檔以及使用者資料的快取的全快取,可以做到每次都直接使用本地快取資料,不用等待網路請求。但 HTML 檔案的快取做不到,對於 HTML 檔案,如果把 Expires / max-age 時間設長了,長時間只使用本地快取,那更新就不及時,如果設短了,每次開啟頁面都要髮網絡請求詢問是否有更新,再確定是否使用本地資源,一般前端在這裡的策略是每次都請求,這在弱網情況下使用者感受到的白屏時間仍然會很長。所以 HTML 檔案的“快取”和跟“更新”間存在矛盾。

桌面時代受限於瀏覽器,H5 頁面無法做更多的優化,現在 H5 頁面是內嵌在客戶端 APP 上,客戶端有更多的許可權,於是客戶端上可以超出瀏覽器的範圍,做更多的優化。

在客戶端有更自由的快取策略,客戶端可以攔截 H5 頁面的所有請求,由自己管理快取,針對上述 HTML 檔案的“快取”和“更新”之間的矛盾,我們可以用這樣的策略解決:

1.在客戶端攔截請求,首次請求 HTML 檔案後快取資料,第二次不發請求,直接使用快取資料。

2.什麼時候去請求更新?這個更新請求可以客戶端自由控制策略,可以在使用本地快取開啟本地頁面後再在後臺發起請求詢問更新快取,下次開啟時生效;也可以在 APP 啟動時或某個時機在後臺去發起請求預更新,提升使用者訪問最新程式碼的機率。

這樣看起來已經比較完美了,HTML 檔案在用客戶端的策略快取,其餘資源和資料沿用上述前端的快取方式,這樣一個 H5 頁面第二次訪問從 HTML 到 JS/CSS/Image 資源,再到資料,都可以直接從本地讀取,無需等待網路請求,同時又能保持儘可能的實時更新,解決了快取問題,大大提升 H5 頁面首屏啟動速度。

注:更多關於客戶端的優化,大家可以自行去查閱相關文件,我在這裡不做介紹了。