微信官方文檔:性能與體驗(yàn)
啟動(dòng)性能
-
代碼包體積優(yōu)化,合理使用分包加載
- 承載更多功能:小程序單個(gè)代碼包的體積上限為2M,使用分包可以提升小程序代碼包總體積上限,承載更多的功能與服務(wù)
- 降低代碼包下載耗時(shí):使用分包后可以顯著減少啟動(dòng)時(shí)需要下載的代碼包大小,在不影響功能正常使用的前提下,有效降低啟動(dòng)耗時(shí)
- 降低小程序代碼注入耗時(shí):使用分包可以避免不必要的組件和頁面初始化
- 降低內(nèi)存占用:分包能夠?qū)崿F(xiàn)頁面、組件和邏輯較粗粒度的按需加載,從而降低內(nèi)存的占用
- 分包的擴(kuò)展功能,獨(dú)立分包,分包預(yù)下載,分包異步化
-
避免非必要的全局自定義組件和插件
如果自定義組件只在某個(gè)分包的頁面中使用,應(yīng)定義在頁面的配置文件中
如果插件只在某個(gè)分包中使用,僅在分包中引用插件 -
控制代碼包內(nèi)的資源文件
小程序代碼包在下載時(shí)會(huì)使用ZSTD算法進(jìn)行壓縮,圖片、音頻,視頻、字體等資源文件會(huì)占用較多代碼包體積,并且通常難以進(jìn)一步被壓縮,對(duì)于下載耗時(shí)的影響較大,所以,這類文件盡可能的部署到CDN,并使用URL引入,建議在代碼包內(nèi)的圖片只包含一些體積小的圖標(biāo)
及時(shí)清理無用代碼和資源
代碼注入優(yōu)化(按需注入,用時(shí)注入)
啟動(dòng)過程中減少同步API的調(diào)用(getSystemInfo、getStorageSync)
避免啟動(dòng)過程進(jìn)行復(fù)雜運(yùn)算
-
首屏渲染優(yōu)化
- 使用按需注入和用時(shí)注入,減少需要初始化的組件數(shù)量
- 啟用初始渲染緩存,可以在非首次啟動(dòng)時(shí),提前將頁面渲染結(jié)果展示給用戶
- 避免引用未使用的自定義組件
頁面渲染時(shí),會(huì)初始化在當(dāng)前頁面配置和全局配置通過usingComponents引用的自定義組件,以及組件所依賴的其他自定義組件,當(dāng)組件不被使用時(shí),應(yīng)及時(shí)從usingComponents中移除
精簡首屏數(shù)據(jù)
首頁渲染的耗時(shí)和頁面的復(fù)雜度正相關(guān),對(duì)于復(fù)雜頁面可以選擇進(jìn)行漸進(jìn)式的渲染,根據(jù)頁面內(nèi)容優(yōu)先級(jí),對(duì)于非關(guān)鍵部分或者不可見的部分進(jìn)行延遲更新
此外,與視圖層渲染無關(guān)的數(shù)據(jù)應(yīng)盡量不要放在data中,避免影響頁面渲染時(shí)間提前首屏數(shù)據(jù)請(qǐng)求
猶豫網(wǎng)絡(luò)請(qǐng)求需要相對(duì)較長的時(shí)間,建議在onload或者更早的時(shí)機(jī)發(fā)起網(wǎng)絡(luò)請(qǐng)求,而不應(yīng)該等待onready之后
- 數(shù)據(jù)預(yù)拉?。盒〕绦蚶鋯?dòng)時(shí),由客戶端通過微信后臺(tái)提前向三方服務(wù)器拉取業(yè)務(wù)數(shù)據(jù),減少用戶等待時(shí)間
- 周期性更新:未打開小程序的情況下,提前從三方服務(wù)器拉取數(shù)據(jù),減少用戶等待時(shí)間
- 緩存請(qǐng)求數(shù)據(jù),通過本地緩存的數(shù)據(jù)進(jìn)行渲染視圖
- 使用骨架屏,灰色的區(qū)塊大致勾勒輪廓,避免展示空白頁面,提升用戶等待意愿
運(yùn)行時(shí)性能
-
合理使用setData
setData的流程
1)邏輯層虛擬DOM樹的遍歷和更新,會(huì)觸發(fā)組件生命周期和observer等
2)將data從邏輯層傳輸?shù)揭晥D層
3)視圖層虛擬DOM樹的更新、真實(shí)DOM元素的更新并觸發(fā)頁面渲染更新-
數(shù)據(jù)通信
對(duì)于第2步,由于小程序的邏輯層和視圖層是兩個(gè)獨(dú)立的運(yùn)行環(huán)境、分屬不同的線程或進(jìn)程,不能直接進(jìn)行數(shù)據(jù)共享,需要進(jìn)行數(shù)據(jù)的序列化、跨線程/進(jìn)程的數(shù)據(jù)傳輸、數(shù)據(jù)的反序列化,因此數(shù)據(jù)傳輸過程是異步的、非實(shí)時(shí)的
使用建議
1)data應(yīng)只包括渲染相關(guān)的數(shù)據(jù),setData的方式更新渲染無關(guān)的字段,會(huì)出發(fā)額外的渲染流程,或增加傳輸?shù)臄?shù)據(jù)量,影響渲染耗時(shí)
2)頁面或組件的data字段,應(yīng)用來存放和頁面或組件渲染相關(guān)的數(shù)據(jù)(即直接在wxml中出現(xiàn)的字段)
3)頁面或組件渲染間接相關(guān)的數(shù)據(jù)可以設(shè)置為純數(shù)據(jù)字段,key使用setData設(shè)置并使用observers監(jiān)聽變化
4)頁面或組件渲染無關(guān)的數(shù)據(jù),應(yīng)掛在非data的字段下
5)避免在data中包含渲染無關(guān)的業(yè)務(wù)數(shù)據(jù)
6)避免使用data在頁面或組件方法間進(jìn)行數(shù)據(jù)共享
7)避免濫用純數(shù)據(jù)字段來保存可以使用非data字段保存的數(shù)據(jù)
8)僅在需要進(jìn)行頁面內(nèi)容更新時(shí)調(diào)用setData
9)對(duì)連續(xù)的setData調(diào)用盡可能的進(jìn)行合并
10)選擇合適的setData范圍,組件的setData只會(huì)引起當(dāng)前組件和子組件的更新,對(duì)于需要頻繁更新的頁面元素,可以封裝為獨(dú)立組建,在組建內(nèi)部進(jìn)行setData,必要時(shí)可以使用CSS contain屬性限制計(jì)算布局、樣式和繪制等范圍
11)setData應(yīng)只傳發(fā)生變化的數(shù)據(jù),建議以數(shù)據(jù)路徑形式鋼鞭數(shù)組中某一項(xiàng)或?qū)ο蟮哪硞€(gè)屬性,而不是每次更新整個(gè)對(duì)象
12)頁面切后臺(tái)后的更新操作,應(yīng)盡量避免,或延遲到頁面onShow后延遲進(jìn)行
13 )控制setData的頻率,每次setData都會(huì)觸發(fā)邏輯層虛擬DOM樹的遍歷和更新,也可能會(huì)導(dǎo)致觸發(fā)一次完整的頁面渲染流程。過于頻繁(毫秒級(jí))的調(diào)用setData,會(huì)導(dǎo)致一下后果:
邏輯層JS線程持續(xù)繁忙,無法正常響應(yīng)用戶操作的事件,也無法正常完成頁面切換
視圖層JS線程持續(xù)處于忙碌狀態(tài),邏輯層->視圖層通信耗時(shí)上升,視圖層收到消息的延時(shí)較高,渲染出現(xiàn)明顯延遲
視圖層無法及時(shí)響應(yīng)用戶操作,用戶滑動(dòng)頁面時(shí)干到明顯卡頓,操作反饋延遲,用戶操作時(shí)間無法及時(shí)傳遞到邏輯層,邏輯層亦無法及時(shí)將操作處理結(jié)果傳遞到視圖層 -
渲染性能優(yōu)化
- scroll事件觸發(fā)頻率很高
- 非必要不監(jiān)聽scroll事件,
- 在實(shí)現(xiàn)與滾動(dòng)相關(guān)動(dòng)畫時(shí),優(yōu)先考慮滾動(dòng)驅(qū)動(dòng)動(dòng)畫(僅<scroll-view>)或wxs響應(yīng)事件
- 不需要監(jiān)聽事件時(shí),不要保留onPageScroll空函數(shù)
- 避免在scroll事件監(jiān)聽函數(shù)中執(zhí)行復(fù)雜邏輯
- 避免在scroll事件監(jiān)聽中頻繁調(diào)用setData或同步API
- 需要監(jiān)控元素曝光情況,建議使用節(jié)點(diǎn)布局相交狀態(tài)監(jiān)聽IntersectionObserver推斷某些節(jié)點(diǎn)是否可見,有多大比例可見(避免監(jiān)聽onPageScroll中持續(xù)調(diào)用selectQuery判斷)
- 建議一個(gè)頁面wxml節(jié)點(diǎn)數(shù)量少于1000個(gè),節(jié)點(diǎn)樹深度少于30層,子節(jié)點(diǎn)數(shù)不大于60個(gè)
- 對(duì)于比較復(fù)雜的數(shù)據(jù)對(duì)象,建議在onload或created時(shí)手動(dòng)賦值到this上,而不是page構(gòu)造時(shí)的參數(shù)傳入
- 選擇高性能的動(dòng)畫實(shí)現(xiàn)方式
優(yōu)先使用CSS漸變、CSS動(dòng)畫、或小程序框架提供的其他動(dòng)畫實(shí)現(xiàn)方式完成動(dòng)畫
在一些復(fù)雜場景下,如果上述方式不能滿足,可以使用wxs響應(yīng)事件動(dòng)態(tài)調(diào)整節(jié)點(diǎn)的style屬性做到動(dòng)畫效果。
避免通過連續(xù)setData實(shí)現(xiàn)動(dòng)畫,不可避免,則盡可能改成自定義組件中的setData -
頁面切換優(yōu)化
- 頁面切換時(shí),會(huì)先調(diào)用前一個(gè)頁面的onHide/onUnload方法,所以避免在onHide/onUnload執(zhí)行耗時(shí)操作
- 頁面預(yù)加載
-
資源加載優(yōu)化
- 控制圖片資源大小
- 避免濫用image組件的widthFix和heightFix,盡量預(yù)先指定圖片尺寸,避免加載完成后二次調(diào)整尺寸
-
內(nèi)存優(yōu)化
- 合理使用分包
- 使用按需注入和用時(shí)注入
- 內(nèi)存分析
- 處理內(nèi)存告警,必要時(shí)使用wx.onMemoryWarning監(jiān)聽內(nèi)存告警時(shí)間,進(jìn)行必要的內(nèi)存清理,釋放一些暫時(shí)不用的組件或者js對(duì)象
- 內(nèi)存泄露
1)小程序長期持有頁面實(shí)例,導(dǎo)致頁面和引用組件無法正常銷毀(事件監(jiān)聽持有頁面this,頁面實(shí)例唄頁面外變量或者全局變量引用,頁面實(shí)例唄異步回調(diào)長時(shí)間引用等)*
2)事件監(jiān)聽未解綁
3)未清理的定時(shí)器