1. 背景 3月份針對線上重點H5項目秒開進行治理,本文將逐步介紹如何通過H5頁面的優化手段來提高 1.5 秒開率。 2. 為什麼要優化 從用戶角度看,優化能夠讓頁面載入得更快、對用戶操作響應更及時,用戶體驗更良好,提升用戶體驗和降低用戶流失率非常重要。其中 Global Web Performan ...
1. 背景
3月份針對線上重點H5項目秒開進行治理,本文將逐步介紹如何通過H5頁面的優化手段來提高 1.5 秒開率。
2. 為什麼要優化
-
從用戶角度看,優化能夠讓頁面載入得更快、對用戶操作響應更及時,用戶體驗更良好,提升用戶體驗和降低用戶流失率非常重要。其中 Global Web Performance Matters for ecommerce報告中也有具體說明優化的重要性。
-
從企業角度看,優化能夠減少頁面請求數或者減小請求所占帶寬,能夠節省可觀的資源成本,最終提高收益轉化。
3. 優化目標
從上圖中可以看出,有些功能變數名稱下可能低於90%,最高的也沒達到96%,離既定98%的目標還有一定差距。
4. H5性能分析
分析工具
-
Lighthouse
-
Chrome DevTools
-
gtmertrix 線上可視化分析工具 https://gtmetrix.com/
Webview載入H5
通常情況分以下幾個階段
-
Webview初始化。
-
到達新的頁面,網路連接,從伺服器下載html,css,js,頁面白屏。
-
頁面基本框架出現,js請求頁面數據,頁面處於loading狀態。
-
出現所需的數據,完成整個頁面的渲染,用戶可交互。從圖形直觀看H5 啟動過程: -
如何縮短這些過程的時間,就成了優化 H5 性能的關鍵。接下來我們詳細看一下各個階段註意的優化點。
優化方案
從以下幾個方面入手:
-
載入策略優化
-
增加骨架屏
-
資源請求優化(靜態資源、圖片以及 webp 、圖片懶載入、組件按需載入)
-
打包資源優化
-
CDN & 緩存
接下來就逐個分析
(1) 載入策略優化
先看一張圖:
https://developers.google.com/web/fundamentals/primers/modules#module-vs-script
從這張圖裡我們能看到什麼,大致能總結為以下四點:
-
預設情況:HTML解析,然後載入 JS,此時 HTML 解析中斷,然後執行 JS,最後 JS執行完成並恢復 HTML解析。
-
defer情況下:HTML 和 JS 並駕齊驅,最後才執行 JS( js腳本在所有元素載入完成後執行,而且是按照js腳本聲明的順序執行,但要等到dom文檔全部解析完才會被執行)。
-
async 情況下:HTML和 JS 並駕齊驅,JS 的執行可能在 HTML解析之前就已完成了 (js腳本是亂序執行的,不管你聲明的順序如何,只要某個js腳本載入完就立即執行)。
-
module情況下:與defer情況類似,只不過在提取的過程中會載入多個 JS 文件而已 (聲明acript標簽type="module"屬性從而擁抱es6的模塊導入導出語法, 載入也和defer差不多,只不過可以載入多個JS文件而已)
項目中實踐示例:
(2) 預載入
prefetch 和 preload
preload 是一個新的 Web 標準,在頁面生命周期中提前載入你指定的資源,同時確保在瀏覽器的主要渲染機制啟動之前。
具體使用如下:
<script rel="prefetch" as="script" href="index.js" />
<script rel="preload" as="script" href="index.js" />
註意:preload 緊挨著 title 放,使其最早介入。
prefetch 是提示瀏覽器,用戶在下次導航時可能會使用的資源(HTML,JS,CSS或者圖片等),因此瀏覽器為了提升性能可以提前載入、緩存資源。prefetch 的載入優先順序相對較低,瀏覽器在空閑的時候才會在後臺載入。用法與 preload 類似,將 rel 的值替換成 prefetch 即可。
preload 是告訴瀏覽器頁面必定需要的資源,瀏覽器一定會載入這些資源,而 prefetch 是告訴瀏覽器頁面可能需要的資源,瀏覽器不一定會載入這些資源。所以建議:對於當前頁面很有必要的資源使用 preload,對於可能在將來的頁面中使用的資源使用 prefetch。
註意:用 preload 和 prefetch 情況下,如果資源不能被緩存,那麼都有可能浪費一部分帶寬,請慎用。非首頁的資源建議不用 preload,prefetch 作為載入下一屏數據來用。
dns-prefetch 和 preconnect
dns-prefetch
DNS 請求需要的帶寬非常小,但延遲較高,這點特別是在手機網路上比較明顯。預讀取 DNS 能讓延遲明顯減少一些(尤其是移動網路下)。為了幫助瀏覽器對某些功能變數名稱進行預解析,你可以在頁面的html標簽中添加 dns-prefetch 告訴瀏覽器對指定功能變數名稱預解析。
dns-prefetch 是一項使瀏覽器主動去執行功能變數名稱解析的功能。dns-prefetch 應該儘量的放在網頁的前面,推薦放在後面。具體使用方法如下:
<link rel="dns-prefetch" href="//*.com">
洗車項目中有體現:
註意:dns-prefetch需慎用,推薦首屏載入資源添加DNS Prefetch
preconnect
和 DNS prefetch 類似,preconnect 不僅會解析 DNS,還會建立 TCP 握手連接和 TLS 協議(如果是https的話)。用法如下:
preconnect
允許瀏覽器在 HTTP 請求實際發送到伺服器之前建立早期連接。可以預先啟動 DNS 查找、TCP 握手和 TLS 協商等連接,從而消除這些連接的往返延遲併為用戶節省時間。
<link rel="preconnect" href="//*.com.cn" />
(3) 骨架屏
從圖上可以看出有白屏情況,FCP 時間超過了 1秒多,解決下來就用了骨架屏來解決白屏情況 並提升 FCP。
骨架屏
就是在頁面資源尚未載入完成以及渲染尚未完成時,需要先給用戶的展示頁面大致結構。直到資源載入完成以及渲染完成後,使用渲染的頁面。骨架屏處理方案也很多,常用方案有以下幾種:
-
首屏:可以在index.html模版中手寫骨架屏相關代碼。
-
其他頁面:可以利用UI提供SVG圖
-
作為SPA中路由切換的loading:需自己編寫骨架屏,推薦兩個成熟方便定製的svg組件去定製骨架屏- react-content-loader和vue-content-loader。
-
骨架圖渲染前不要出現任何網路請求,在此之前 HTML 內容不要超過 4KB。
我這裡採用了固定的骨架屏SVG打包自動註入到模板方式。並產出了基於vite 的自動化註入骨架屏和無阻塞緩存資源文件@auto/vite-plugin-cdn私有插件。
舉個