![](https://www.eyoucms.com/skin/img/qq.png)
- 业务客服
- 付费修改
- 加入Q群
- 微信客服
工作日 8:30-12:00 14:30-18:30
本文主要是根据微信小程序官方优化建议和《2018微信公开课第七季上海站·小程序专场》的性能优化方案,针对性我们的小程序项目进行性能优化实践,将过程记录下来,方便以后查看,同时也希望能帮助到其他小伙伴,做好性能优化。毕竟一切性能优化都是为了更好的用户体验。
这些问题的场景都反映了小程序的性能问题,直接影响到用户体验。
官方建议从这两方面进行优化:
小程序在整个启动流程中,一般需要完成几项工作:
开发者可以在第2,3去优化小程序的启动性能。
小程序在首次打开时,会去下载并执行代码包,随着代码包大小的上升,耗时也会相应增加。可以采取以下方案:
对开发者而言,能使小程序有更大的代码体积,承载更多的功能与服务;而对用户而言,可以更快地打开小程序,同时在不影响启动速度前提下使用更多功能。
建议开发者按照功能的划分,拆分成几个分包,当需要用到某个功能时,才加载这个功能对应的分包。
我们的一个小程序在两年多前开始开发的,在设计之初,我们没有考虑到这一点,当时也没有小程序分包的功能。好吧,我们还是迎来了这个问题。
微信小程序在开发文档中明确指出,小程序的所有包大小必须限制在2M以内,超过大小,就算在开发者工具中都不能正常预览,更不能上传发版。解决问题的方法:
将静态资源图片压缩,因为小程序的压缩算法对图片的压缩微乎其微,于是互,笔者对图片进行一轮压缩,并且将重复使用的图片,进行了公共提取,虽然官方推荐使用网络图片,但是还需要去维护静态资源,嫌麻烦,就放弃。
将项目中的弃用的页面,以及不用的三方,进行了一波清除。
很多项目现在都是通过webpack打包成不通的分包,资源懒加载的形式来优化,小程序也提供了这个功能:分包,笔者按照按照功能划分的原则,将同一个功能下的页面和逻辑放置于同一个目录下,成为一个分包。
注意:1. 自定义第三方组件,需要放在主包内,miniprogram_npm文件会直接打到主包里;2. 小程序的tab切换页,必须放在主包里。
分包预下载是为了解决首次进入分包页面时的延迟问题而设计的。如果能够在用户进入分包页面之前就预先将分包下载完毕,那么进入分包页面的延迟就能够尽可能降低。
用户进行了某个操作,再去下载分包,延迟操作用户体验很差,于是乎笔者对上面的分包设置分包预下载。在 app.json
文件中配置:
"preloadRule": {
"pages/work/index": {
"network": "all",
"packages": [
"package-work",
"package-field-statistics"
]
},
"pages/appeal/index": {
"network": "all",
"packages": [
"package-appeal"
]
}
},
复制代码
这里建议不要一次性把所有分包预下载,这样的操作同样回带来性能问题。
小程序中的某些场景(如广告页、活动页、支付页等),通常功能不是很复杂且相对独立,对启动性能有很高的要求。使用独立分包,可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。
建议开发者将部分对启动性能要求很高的页面放到特殊的独立分包中。
项目中没有适合的场景,尚未实践。
大部分小程序在渲染首页时,需要依赖服务端的接口数据,接口请求放到页面的生命周期 onLoad
中,而不是 onReady
里。 `:
监听到页面加载,就校验登录情况,请求页面数据
onLoad: function (options) {
app.checkAuth((error, token) => {
if (error) {
return
}
// 请求该页面的数据
})
},
复制代码
小程序提供了wx.setStorageSync等异步读写本地缓存的能力,数据存储在本地,返回的会比网络请求快。
登录成功后将用户的token,以及用户信息都可以缓存到本地,记得退出登录的时候清楚缓存,:joy:。
/**
* 设置本地 token 缓存
* @param {Object} session 服务器返回的数据
* @param {String} session.access_token 存取token
* @param {String} session.refresh_token 刷新token
* @param {String} session.expires_in 有效期限,以秒为单位
*/
export function set(session) {
const localSession = Object.assign({}, session, {
expires_timestamp: getExpireTimestamp(session.expires_in)
});
wx.setStorageSync(SESSION_KEY, localSession);
_token = session.access_token;
}
export function clear() {
wx.removeStorageSync(SESSION_KEY);
clearTimeout(refresh_timer);
_token = null;
}
复制代码
推荐开发者延迟请求非关键渲染数据,缩短网络请求时延,与视图层渲染无关的数据尽量不要放在 data 中,以免传输垃圾数据,加快首屏渲染完成时间。
通过id请求详情的情况,id在渲染层不需要,就可以不把id,定义在data中:
// 原来代码
data: {
id: ‘’,
// ….
},
onLoad: function (options) {
this.setData({
id: options.id
})
// ….
}
// 改写后 不把id定义到data中
data: {
// ….
},
app.checkAuth((error, token) => {
const id = options.id === undefined ? '' : options.id;
this.id = id
})
复制代码
接口返回的数据要做数据处理,不要直接都塞给data,减少冗余数据的双线程回传。也是 精简首屏数据优化的一部分。
在小程序启动流程中,会顺序执行app.onLaunch, app.onShow, page.onLoad, page.onShow, page.onReady,所以,尽量避免在这些生命周期中使用Sync结尾的同步API,如 wx.setStorageSync,wx.getSystemInfoSync 等。
项目中没有这样使用,有先见之明。:smile:
小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。
而 evaluateJavascript 的执行会受很多方面的影响,数据到达视图层并不是实时的。
** 常见的 setData 操作错误 **
导致了两个后果:
目前项目代码还是比较规范的,我们并没有把setData当成一个普通的对象去调用,晓得每次使用都需要两个线程间通信,WebView再去渲染的。哇,好棒。
由setData的底层实现可知,我们的数据传输实际是一次 evaluateJavascript 脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程。
目前每个接口的数据量并大,数据的量级还没达到影响脚步执行的程度,有需要的话再优化吧。
当页面进入后台态(用户不可见),不应该继续去进行setData,后台态页面的渲染用户是无法感受的,另外后台态页面去setData也会抢占前台页面的执行。
A页面上有个定时器,此时打开了B页面,A页面的定时器还在运行,继续抢占B页面的资源,B页面卡顿了,但是并不是B页面的造成的性能问题,这种问题就不太好排查。希望大家都能做个有始有终的人,定时器不用了要清除。下面demo,定时器在 onHide
时要清除掉。切记切记:point_down:
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
clearTimeout(getTodaytime)
this.updateNowTime()
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
// 取消定时器 防止小程序内存不足,崩溃
clearTimeout(getTodaytime)
},
updateNowTime() {
getTodaytime = setInterval(() => {
const myDate = new Date();
const hours = myDate.getHours())
const minutes = myDate.getMinutes())
const seconds = myDate.getSeconds())
const newTime = hours + ':' + minutes + ':' + seconds;
this.setData({
newTime: newTime
})
}, 1000)
},
复制代码
项目中展示没用使用该事件。
在需要频繁更新的场景下,自定义组件的更新只在组件内部进行,不受页面其他部分内容复杂性的影响。
工作日 8:30-12:00 14:30-18:00
周六及部分节假日提供值班服务
工作日 8:30-12:00 14:30-18:30
深圳SEO优化公司盐城品牌网站设计多少钱松原网站建设设计哪家好崇左建网站公司天门百度竞价报价临沧外贸网站建设价格天津百度网站优化推荐沧州关键词按天扣费醴陵百姓网标王推广价格铜陵百度关键词包年推广推荐太原百度竞价包年推广价格镇江网站关键词优化哪家好玉林seo公司潜江优化价格通辽网站建设设计公司龙岗营销型网站建设哪家好安庆百度竞价推荐娄底网站推广方案推荐黄山百姓网标王推广报价黄冈SEO按天收费天门网站建设哪家好周口seo优化推荐坂田百度竞价包年推广价格东营网站优化排名推荐兴安盟网站推广方案公司巴中网站关键词优化石家庄百度标王丹竹头SEO按天计费遵义网站关键词优化公司布吉网站优化软件多少钱青岛网站关键词优化多少钱歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运