1. 背景介紹
在偏重活動運營的電商App中,受制于App版本審核,具備開發周期短、可靈活發布等特點的H5頁面受到青睞,承載了很多重要業務,但App Webview存在令人煩惱的性能問題,特別突出的是加載速度慢,和Native頁面相比用戶體驗較差,因此本文將從H5加載速度優化方面,總結了XCache、Prefetch、容器預熱三種優化方案,以及上線后的提速效果分享,
2. XCache離線快取提速方案
2.1 方案背景
為了有效解決 Android H5的性能問題,除了使用Android WebView自身的快取機制,還可以自己針對某一需求場景構建快取機制,
通常來說,加載一個h5頁面最耗時的部分就在于頁面資源的下載,如html、css、js以及圖片檔案,如果這些檔案不需要下載,那么剩下的時間開銷基本就是業務資料的下載以及頁面的決議渲染了,
2.2 方案總體介紹

- 首先構建Admin后臺管理系統,主要幫助開發人員對H5資源進行配置管理,主要包括資源的版本管理、總容量管理以及資源的發布,
- XCache服務器負責提供資源的下載介面,CDN作為資源鏡像,在Server介面連續失敗后提供備用介面,
- 移動端在合適的時機拉取資源配置表,以及資源本身,并在WebView發起資源請求時,判斷是否命中資源快取,從而提高加載速度(尤其是弱網環境),并節省流量,
- 在資源被訪問以及命中快取后,將相關的資料進行上傳統計,從而協助發現問題、調整策略,
2.3 Android端具體方案介紹

- 資源配置表檢查更新介面的觸發時機:啟動/打開webview/切前臺/退出webview,配置表需要實時更新,但是如果連續觸發,疲勞度控制在30s內不重復觸發,
- 資源配置表介面的例外兜底機制:介面后端連續例外code 5次,使用的CDN上最新資源鏡像(APP內置最新CDN鏡像鏈接),
- 根據和上一次的資源配置表進行diff,獲取資源的"增、刪、更新"資訊,其中,同樣的資源根據版本號進行更新,
- 資源的下載時機:當APP空閑時機,并且處于Wi-Fi環境,同時子執行緒佇列下載優先級為最低,下載下來的資源需要進行MD5校驗防止惡意攻擊,
- 快取策略:在移動端支持兩級快取:記憶體快取、磁盤快取,均以LRU作為快取策略,記憶體快取的優先級大于磁盤快取,其中,記憶體快取容量大小設定為10M(記憶體緊張釋放記憶體快取), 磁盤快取容量大小設定為100M,
- 在H5頁面資源請求中,如果命中了配置表中的資源,則優先尋找本地快取,快取命中則直接使用,若沒有發現本地快取(原因有很多,比如非Wi-Fi環境下資源沒有被提前下載),則自行下載使用的同時,將資源放入記憶體快取以及磁盤快取,方便第二次的快取命中,
2.4 提速效果總結
2.4.1 白屏時間更短
- 以簽到頁為例, Android端頁面白屏100ms以內的占比從原來的28.4%提升到了71.2%,
2.4.2 更為用戶省流量
- 每年XCache將為用戶節省的流量約為53.63TB,(PV * 快取命中率 * 資源大小 = 省流)
2.4.3 留住了更多“沒有耐心”的用戶
- 以簽到頁為例, 每天因為不愿意等H5白屏而選擇退出的用戶至少減少了1200名,
3. Prefetch資料并行加載提速方案
3.1 方案背景
如果說XCache離線快取提速方案解決的是H5資源檔案下載慢的問題,那么Prefetch并行加載就是從資料的角度來進行的優化,

- 以超級會員頁H5為例,整個H5的加載流程是串行的,業務介面必須在H5資源ready、以及js環境ready之后才會發出;
- 針對待優化頁面,如果在H5頁面被打開的同時,客戶端協助H5提前將業務請求發出,并維護該資料在記憶體中,并通過JsBridge將資料提供給H5,H5便不需要再發出請求,從而利用并行特性,縮短H5的白屏時間,
3.2 方案總體介紹

- 在客戶端首次打開H5頁面時,拉取prefetch組態檔,其中動態配置了待優化頁面、協助客戶端完成url—>api,
- 考慮到H5頁面的業務請求不僅依賴于Native注入的Native Cookie,還依賴于H5的一些特有Cookie,因此客戶端在拉取配置表的同時,需要觸發一次H5 Cookie的請求,且該Cookie不會污染Native Cookie,僅用于Prefetch請求,
- 當客戶端攔截并感知到待優化頁面被打開時,主動拉取H5側的業務資料,用hash演算法將資料存在記憶體Map中,其中hash(url+api)作為key,并約定H5側通過jsbridge以及相同的key來獲取資料,該資料的生命周期很短,退出H5或者被H5側拿走即清空,
- 最后在H5側的相關頁面中,修改少量邏輯,在獲取業務資料的地方,優先通過jsbridge向客戶端拉取業務資料,如果拉取成功,便省去了自行請求的時間,從而達到優化的目的,如果拉取失敗,則降級為自行請求的舊邏輯,
3.3 業內方案對比
| 云音樂Prefetch方案 | 本Prefetch方案 | |
|---|---|---|
| 差異 | H5嚴格信任客戶端的異步回呼資料, 無錯誤兜底 | H5僅在當前拉取一次客戶端資料, 有錯誤兜底 |
| 優點 | Prefetch優化的命中率較高 | 有Prefetch錯誤兜底, 白屏率更低; 前端出現白屏一定不會是Prefetch的引入導致的 |
| 缺點 | 無兜底, 兩端任何細節出錯就是白屏, 出錯難排查 | 如果介面過于耗時(>800ms),Prefetch優化會失效, 因此總體的優化命中率會變低,大概88% |
由于業內方案中,任何細節出錯(譬如Prefetch配置表拉取失敗、客戶端攔程序序出錯等等),都會導致H5側都無法獲取到資料,從而導致白屏,
因此我們采用了更加安全、以及解耦的方案,H5僅在當前拉取一次客戶端資料,并加入兜底機制,降低由于優化導致的白屏情況,以及出現白屏不用花精力在“是不是因為Prefetch導致的”,而因為介面過于耗時導致優化成功率降低到88%左右,也是完全可以接受的,
3.4 提速效果總結
3.4.1 輕量級
- 不需要預作業, 不拖慢App速度,因為Prefetch是在用戶點擊進入H5的那一刻才開始作業, 所以不會存在類似于XCache的預加載環節,
3.4.2 H5頁面呈現速度更快
- 為了排除其他業務對優化效果量化的影響,Android端單獨上線Prefetch,同一時間iOS未上線Prefetch,
- 簽到頁H5的首屏完整呈現達標率均值提升6.3%, 對照組iOS降低6.7%;超會頁H5的首屏完整呈現達標率均值提升4.1%, 對照組iOS降低2.4%
4. 容器預熱提速方案
4.1 方案背景
當App首次打開時,默認是并不初始化瀏覽器內核的;只有當創建WebView實體的時候,才會創建WebView的基礎框架,所以啟動瀏覽器內核的開銷都算到了用戶首次打開H5頁面里,WebView首次初始化后,一些WebView共用的全域服務或資源物件仍沒有釋放,因此第二次打開H5頁面會變快,
| 首次H5打開時間 | 第二次H5打開時間 | |
|---|---|---|
| Android WebView | 1554.6ms | 1044.1ms |
經過測驗,第二次H5的打開速度比首次打開要快32.8%,
4.2 方案總體介紹
| 容器預熱 | 選擇性的容器預熱 | |
|---|---|---|
| 優點 | 有效的減少WebView在App中的首次打開時間 | 同左,且盡量減少額外的記憶體消耗 |
| 缺點 | 不可避免的額外記憶體開銷 | - |
- 我們可以在App啟動之后,并且空閑時,預先將容器WebView進行一次初始化, 當第二次初始化WebView的時候速度就快多了, 或者直接將其拿來使用,
- 同時,我們針對“不愛打開H5”的用戶,有選擇性的進行容器預熱,從而盡量避免額外的記憶體開銷,
4.3 提速效果總結
- 由于方案未上線,預計將為用戶減少30%以上的首次H5打開時間,
5. 文章總結
相對于React Ntive、Flutter等跨端方案,H5開發有著更加靈活的便利性,因此總能在移動互聯網的浪潮中占據一席之地,本文從資源快取、資料并行加載、容器預熱三個方面對H5進行了加載速度優化,都有比較好的提速效果,提升了用戶的使用體驗,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259859.html
標籤:其他
下一篇:PicGo:搭建圖床
