前言
由于小程序本身層面做了一些優(yōu)化,展示比h5在某些更優(yōu)。但目前隨著代碼量的增加,頁(yè)面本身顯示得越來(lái)越不“小程序”了。本次著手從表現(xiàn)層面進(jìn)行優(yōu)化。
現(xiàn)場(chǎng)
- 首頁(yè)列表越滾動(dòng)越卡頓。
在請(qǐng)求20次后幾乎卡死,究其原因發(fā)現(xiàn)是業(yè)務(wù)調(diào)用setComponent時(shí),框架onion在updateComponent設(shè)置過(guò)多數(shù)據(jù)導(dǎo)致 。每次重新set時(shí),會(huì)把新增數(shù)據(jù)合并到原有的數(shù)據(jù)再重新調(diào)用setData,這樣讓數(shù)據(jù)量成倍增加,但渲染時(shí)間卻如下圖,超過(guò)1M報(bào)錯(cuò)
image
[圖片來(lái)源網(wǎng)絡(luò)]
-
優(yōu)化前,時(shí)間呈上圖函數(shù)增長(zhǎng)。最后一條接近3s
image-
優(yōu)化后,render的時(shí)間比較平穩(wěn),維持50ms以下。
image
-
- 優(yōu)化方法
用一個(gè)新的數(shù)組來(lái)存儲(chǔ)新增的數(shù)據(jù),這樣保證每次數(shù)據(jù)量體積穩(wěn)定。
_updateComponent(name, indexs) {
let data = {},
newData = {},
componentKey = 'components.' + name
data[componentKey] = this.data.components[name]
if (indexs && indexs.length) {
Object.keys(data[componentKey]).forEach(key=>{
if (indexs.indexOf(key) > -1){
newData[componentKey + '.' + key] = data[componentKey][key];
}
})
data = newData
}
this.setData(data)
}
2.店鋪首頁(yè)
通過(guò)小程序模擬器的Audits檢查頁(yè)面問(wèn)題

image
a.圖片相關(guān)
-
大體積圖片
- 圖片統(tǒng)一限高裁切,部分圖片過(guò)大,占用內(nèi)存資源。通過(guò)添加w和h參數(shù)對(duì)圖片大小控制
-
圖片文件格式
- 判斷是否支持webp?目前通過(guò)平臺(tái)判斷,非ios下則在圖片鏈接后追加webp。當(dāng)然更好的方式是通過(guò)加載是否支持webp的圖片來(lái)實(shí)現(xiàn),以后微信可能支持顯示webp。
function supportWebpBySystem() {
supportWebp = false;
wx.getSystemInfo({
success: function(res){
var platform = res.platform || '';
if (platform.toLocaleLowerCase() !== 'ios') {
supportWebp = true;
}
},
fail: function(){
supportWebp = false;
},
});
}
- 減少一次性圖片請(qǐng)求
- 使用圖片懶加載。在未處理前最多同時(shí)請(qǐng)求30+張圖片,這無(wú)論是在流量上還是性能上都有一些損失。由于我們采用組件開(kāi)發(fā)的形式,考慮到一些特殊情況,所以在組件內(nèi)部新增一個(gè)
lazyLoad變量來(lái)控制懶加載。
組件的每一個(gè)元素上都有一個(gè)唯一標(biāo)示no,而它又作為class。這樣就可以通過(guò)createIntersectionObserver來(lái)監(jiān)聽(tīng)加載
- 使用圖片懶加載。在未處理前最多同時(shí)請(qǐng)求30+張圖片,這無(wú)論是在流量上還是性能上都有一些損失。由于我們采用組件開(kāi)發(fā)的形式,考慮到一些特殊情況,所以在組件內(nèi)部新增一個(gè)
用于推斷某些節(jié)點(diǎn)是否可以被用戶看見(jiàn)、有多大比例可以被用戶看見(jiàn)。
支持版本 >= 1.9.3
function createIntersectionObserver(){
var self = this,
key,
id = this.id.replace('.','-'),
lazyLoad = this.data.lazyLoad;
setTimeout(() => {
for(let i = 0;i < this._data.no; i++){
key = id + '-' + i;
(function(key){
wx.createIntersectionObserver().relativeToViewport({bottom: 20}).observe('.' + key, (res) => {
if (res.intersectionRatio > 0 && !lazyLoad[key]) {
self.setData({
['lazyLoad.' + key] : true
});
}
});
})(key);
}
}, 300); // 延時(shí)是為了掛載完再監(jiān)聽(tīng),這里只是隨便寫(xiě)的一個(gè)數(shù)字,具體掛載完的時(shí)間沒(méi)有測(cè)試過(guò)
}
b.變量管理
與UI沒(méi)關(guān)系的變量,不通過(guò)setData來(lái)進(jìn)行設(shè)置。直接通過(guò)變量_data來(lái)管理,這樣既能減少調(diào)用setData的次數(shù),又能縮小data的大小。
參考
【微信小程序】性能優(yōu)化https://juejin.im/post/5b9f5d55e51d450e4006a9e5
徹底解決長(zhǎng)列表頁(yè)setData超過(guò)1M時(shí)報(bào)錯(cuò)和嚴(yán)重卡頓的問(wèn)題


