jeremygo

jeremygo

我是把下一颗珍珠串在绳子上的人

微信小程序啟動性能優化

最近在做微信小程序的冷啟動耗時優化,查閱了一下 小程序官方文檔 後發現已經寫得非常詳盡細緻了,這裡做一下記錄整理,突出開發者重點關注的部分。

啟動定義#

以「用戶打開小程序」為起點,到小程序「首頁渲染完成」為止。

小程序「首頁渲染完成」的標誌是首個頁面 Page.onReady 事件觸發。由於啟動流程的差異,小程序定義的「首頁渲染完成」不等同於瀏覽器的 DOMContentLoadedload 事件。

啟動流程及耗時影響#

從打開微信小程序到首頁展示,需要經歷如下過程:

各流程不是串行的,會儘可能並行,不能簡單分階段加和計算總啟動耗時

image

資源準備#
小程序相關信息準備

在用戶首次訪問小程序、小程序版本更新或使用長期未使用的小程序時,微信客戶端需要從微信後台獲取小程序的頭像、暱稱、版本、配置、權限等基本信息,以對小程序進行必要的版本管理、權限控制和校驗等。

為了在保證信息實時性的前提下,儘量降低對啟動耗時的影響,這些信息會在本地緩存,並通過一定的機制進行更新。

小程序版本發布時,會導致啟動時需要同步請求的比例上升,進而導致平均啟動耗時的上漲。因此,建議開發者 合理規劃版本發布

運行環境準備

小程序的運行環境包括小程序進程、客戶端原生部分的系統組件和 UI 元素(如 導航欄、tabBar 等)、渲染頁面使用的 WebView 容器、開發者 JavaScript 代碼的運行環境、小程序基礎庫等等。

部分環境(如 JavaScript 引擎、小程序基礎庫)需要在執行小程序代碼之前準備完成,其他的會在啟動過程中並行進行。

為了儘可能的降低運行環境準備對啟動耗時的影響,微信客戶端會根據用戶的使用場景和設備資源的使用情況,依照一定策略在小程序啟動前對運行環境進行部分地預加載,以降低啟動耗時。

代碼包準備

在用戶首次訪問小程序或小程序版本更新時,需要根據用戶訪問的頁面,從微信後台獲取代碼包地址,從 CDN 下載小程序代碼包,並對代碼包進行校驗。根據小程序頁面所在分包和使用的插件不同,一次啟動可能需要下載多個代碼包或插件包。

除了啟動過程,代碼包下載在頁面跳轉、預下載、使用 分包異步化 等過程中也會觸發。

為了在保證用戶儘可能訪問新版本的前提下,儘量降低對啟動耗時的影響,小程序代碼包會在本地緩存,並通過一定的機制進行更新。
為了降低代碼包下載的耗時,微信還採用了 代碼包壓縮、增量更新、更高效的網絡協議、CDN 預連接、代碼包復用 等方式

考慮到包大小對用戶體驗的影響,平台限制單個小程序代碼包的大小上限為 2M。為了保證啟動速度,開發者應該儘可能的控制啟動時用到的代碼包大小。具體方法可以參考《代碼包體積優化》

小程序代碼注入(邏輯層)#

小程序啟動時需要從代碼包內讀取小程序的配置和代碼,並注入到 JavaScript 引擎中。在主包代碼注入過程中,會觸發小程序的 App.onLaunchApp.onShow 生命週期。如果小程序使用了插件或擴展庫,在注入開發者代碼之前,還會先注入對應插件和擴展庫的代碼。

在部分平台上,微信客戶端會使用 V8 引擎的 Code Caching 技術對代碼編譯結果進行緩存,降低非首次注入時的編譯耗時。

由於「首頁渲染」需要使用邏輯層發送的數據,如果小程序代碼注入耗時過長,會延遲「首頁渲染」開始的時間。建議開發者參考《代碼注入優化》章節進行優化。

小程序代碼注入(視圖層)#

開發者的 WXSSWXML 會編譯成 JavaScript 代碼注入到視圖層,包含頁面渲染需要的頁面結構和樣式信息。

視圖層和邏輯層的小程序代碼注入是並行進行的。

由於「首頁渲染」需要使用視圖層的頁面結構和樣式信息,如果小程序代碼注入耗時過長,會影響渲染數據從邏輯層到達視圖層的時間,影響「首頁渲染」的耗時。

雖然開發者不能直接修改視圖層生成的 JS 代碼,但是可以通過使用「按需注入」、移除未使用的自定義組件等方式降低這部分耗時。

首頁(初次)渲染#

在邏輯層小程序代碼注入完成後,小程序框架會根據用戶訪問的頁面,進行頁面組件樹初始化,生成初始數據發送到視圖層,並依次觸發首頁的 Page.onLoad, Page.onShow 生命週期。

在完成視圖層代碼注入,並收到邏輯層發送的初始數據後,結合從初始數據和視圖層得到的頁面結構和樣式信息,小程序框架會進行小程序首頁的渲染,展示小程序首屏,並觸發首頁的 Page.onReady 事件,標誌小程序啟動過程完成。

首頁渲染耗時是啟動過程的最後一環,直接影響小程序的啟動耗時。耗時長短與頁面結構複雜度、參與渲染的自定義組件數量有關。建議開發者參考《首屏渲染優化》章節進行優化。

如果啟用了「按需注入」,部分組件代碼注入會被延遲到本階段執行,導致階段耗時上漲,但總耗時一般會下降。

首屏內容展示#

「首頁渲染」完成後,小程序啟動流程完成,Loading 消失,此時一般情況下用戶應該能立刻看到首屏內容。如依賴網絡請求則需要等待 setData 進行頁面更新後才會展示,可先展示「骨架屏」來避免白屏,以優化用戶體驗。

異步 setData 觸發繪製的首屏內容展示不一定會計入啟動耗時統計,但是會延遲用戶看到頁面內容的時間,影響用戶體驗。建議開發者參考《首屏渲染優化》章節進行優化。

優化策略#

在小程序啟動流程中,代碼包準備、小程序代碼注入和首頁渲染的耗時是與小程序本身相關的,開發者可以從以下方面進行優化工作:

  • 代碼包體積優化
    • 分包加載、獨立分包、分包異步化
      • 普通分包加載注意不能相互引用,可使用分包異步化解決
      • 獨立分包不需要下載主包,即也不能依賴主包
    • 避免非必要的全局自定義組件和插件
    • 控制代碼包內的資源文件:圖片使用 CDN 引入
    • 及時清理無用代碼和資源:結合開發者工具提供的 代碼靜態依賴分析 使用
  • 代碼注入優化
    • 使用按需注入和用時注入:結合 避免非必要的全局自定義組件和插件 使用
    • 啟動時減少同步 API 調用:在小程序初始化代碼(Page,App 定義之外的內容)和 App.onLaunch, App.onShow, Page.onLoad, Page.onShow 幾個生命週期中,避免阻塞當前 JS 線程
    • 啟動時減少複雜運算:同上
  • 首屏渲染優化
    • 啟用按需注入和用時注入:減少需要初始化的組件數量
    • 啟用初始渲染緩存:二次啟動跳過邏輯層初始化過程
    • 避免引用未使用的自定義組件
    • 精簡首屏數據:與視圖層渲染無關的數據儘量不要放在 data
    • 提前首屏數據請求:在 Page.onLoad 或更早的時機發起網絡請求
    • 本地緩存請求數據:wx.setStoragewx.getStorage
    • 骨架屏
  • 其他優化建議
    • 控制版本發布頻率
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。