⼩程序性能优化⽅案——让你的⼩程序如此丝滑
⼩程序如果想要优化性能,有关键性的两点:
1. 提⾼加载性能
2. 提⾼渲染性能
接下来分别来介绍⼀下:
提⾼加载性能
⾸先,问⼀个问题,当⽤户点击⼩程序后发⽣了什么?
上图中的三个状态,我们经常遇到,它们分别对应⼩程序的下⾯三个状态:
有三个点的⽩屏(左侧):下载代码包的阶段
没有三个点的⽩屏(中间):业务代码注⼊和渲染的阶段
加载中(右边):业务代码中异步请求数据
总的来说,⼩程序呈现到⽤户⾯前,实际上经历了下⾯两个阶段:
1. 运⾏环境的加载
2. 下载代码包
下⾯具体介绍这两个阶段:
运⾏环境预加载
这步是做的。会在⽤户打开⼩程序之前就已经准备好环境,⽤户点击⼩程序⼊⼝后,直接下载⼩程序的代码包即可。
下载代码包启动⼩程序
⼩程序代码包⾥⾯的代码,不是⼩程序的源代码,⽽是编译、压缩、打包之后的代码包。
下图中,左侧的“预加载”对应的是运⾏环境的预加载,右侧的“⼩程序启动” 对应的是下载代码包启动⼩程序。
⼩程序提供的运⾏环境,分为逻辑层(AppService)和视图层(webView),逻辑层是执⾏javascript的
地⽅,视图层是渲染页⾯的地⽅。当⼩程序的代码包下载完毕后,业务代码分别注⼊逻辑层和渲染层。
提升加载性能的最最最关键性⼀点是,控制包的⼤⼩,这个也是官⽅的说法。
控制包的⼤⼩
提升体验最直接的⽅法是控制⼩程序包的⼤⼩,基本上可以说,1M的代码包,下载耗时1秒左右。
控制包的⼤⼩的措施
压缩代码,清理⽆⽤的代码
图⽚放在cdn
采⽤分包策略
分包预加载
独⽴分包(版本要求有点⾼)
除了上⾯讲的控制包的⼤⼩,对异步请求的优化也很重要。
对异步请求的优化
onLoad 阶段就可以发起请求,不⽤等ready
请求结果放在缓存中, 下次接着⽤
请求中可以先展⽰⾻架图
先反馈,再请求。⽐如说,点赞的按钮,可以先改变按钮的样式,再发起异步请求。
提升渲染性能
setData ⼲了啥
每调⽤⼀次setData, 都是逻辑层向渲染层的⼀次通讯,这个通信还不是直接传给webView, ⽽是通过⾛了native层,通讯的开销很⼤。
渲染层收到通讯后,还需要重新渲染出来,所以,emmm, ⼀次setData带来两次开销:通信的开销 + webview更新的开销。
在数据传输时,逻辑层会执⾏⼀次JSON.stringify来去除掉setData数据中不可传输的部分,之后将数据
发送给视图层。同时,逻辑层还会将setData所设置的数据字段与data合并,使开发者可以⽤this.data读取到变更后的数据。
减少setData的数据量
如果⼀个数据不能会影响渲染层,则不⽤放在setData⾥⾯
合并setData的请求,减少通讯的次数
这个很好理解吧
列表的局部更新
在⼀个列表中,有n条数据,采⽤上拉加载更多的⽅式,假如这个时候想对其中某⼀个数据进⾏点赞操作,还能及时看到点赞的效果
此时,可以采⽤setData全局刷新,点赞完成之后,重新获取数据,再次进⾏全局重新渲染,这样做的优点是:⽅便,快捷!缺点是:⽤户体验极其不好,当⽤户刷量100多条数据后,重新渲染量⼤会出现空⽩期(没有渲染过来)
如果采⽤布局刷新,将点赞的id传过去,知道点的是那⼀条数据, 将点赞的id传过去,知道点的是那⼀条数据。
重新获取数据,查相对应id的那条数据的下标(index是不会改变的),⽤setData进⾏局部刷新
this.setData({    list[index] = newList[index]})
⼩⼼后台页⾯的js
⼩程序中可能有n个页⾯,所有的这些页⾯,虽然都拥有⾃⼰的webview(渲染层),但是却共享同⼀个js运⾏环境。也就是说,当你跳到了另外⼀个页⾯(假设是B页⾯),本页⾯(假设是A页⾯)的定时器等js操作仍在进⾏,并且不会被销毁,并且会抢占B页⾯的资源。
在h5的环境中,当我们跳转到其他页⾯,⽼页⾯的js环境会被⾃动销毁,定时器什么都被销毁掉了,因此我们不需要关⼼⽼页⾯中,还有哪些js代码可能还会执⾏。
但是在⼩程序中,我们必须⼿动的“清理”掉这样的代码。
⼩⼼onPageScroll
pageScroll 事件,也是⼀次通讯,是webview层向js逻辑层的通讯。这次通讯也是开销较⼤,如果考虑到这个事件被频繁的调⽤,回调函数如果有复杂的setData的
话,emmmmm,性能就会很差了。
⼩⼼获取节点位置
在h5 中的环境中,为了实现懒加载、下拉加载,我们不得不去获取节点的位置。
为啥说不得不,是因为我们本可以⽤新的api ——intersectionObject去轻松实现(google等主流浏览器都已经⽀持了),但是的内置X5浏览器很遗憾的不⽀持。
没想到,在⼩程序的环境中,竟然良⼼发现,⽀持intersectionObject api, 因此获取节点的信息,尽量还是⽤这api 吧。
尽可能使⽤⼩程序组件
⾃定义组件的更新只在组件内部进⾏,不受页⾯其他不能分内容的影响;⽐如⼀些运营活动的定时模块可以单独抽出来,做成⼀个定时组件,定时组件的更新并不会影响页⾯上其他元素的更新;各个组件也将具有各⾃独⽴的逻辑空间。每个组件都分别拥有⾃⼰的独⽴的数据、setData调⽤
记录优化后的数据,和优化前进⾏对⽐
如果我们记录下每⼀个页⾯的优化前后的⾸屏渲染数据,并且对⽐,可以很好的分析每⼀个页⾯的性能提升有多少,从⽽判断⾃⼰有没有在做⽆⽤功。
可以先简单约定⼀下,⾸屏渲染时间的含义为:从⼩程序页⾯onload事件算起,页⾯发起异步请求,请求回来后,把数据通过setData 渲染到页⾯后,上述⼀整个流程所花费的时间。
但是,⼀个⼩程序项⽬往往会有很多个页⾯,⼿动记录每⼀个⼩程序的⾸屏渲染时间,很⿇烦。
我们可以改造this.setData⽅法如下:
this._startTime = new Date().getTime();let fn = this.setData;this.setData = (obj = {}, handle = '') => {  let now = new Date().getTime();    // 上报渲染所需要的时间  log(now - this._startTime)  fn.apply(this, [obj, handle]);};上⾯的伪代码改写了this.setData⽅法,简单的加⼊了上报时间点逻辑,⼤家可以根据⾃⾝的需求进⾏改造
优化⼼得
相⽐于上⾯的优化策略,最重要的是出⼩程序中的性能瓶颈。在⾃⼰的优化实践中,遇到了下⾯的问题:
1. 下拉加载更多,特别特别卡,通过列表局部更新的技巧,发现性能改善不⼤。后来发现,是因为⾸页需要监听scroll事件,导致scroll事件被频繁的触发,回调函数中有耗时
操作,导致onreachBottom事件被阻塞了,也就是说,要等⼤概1~2秒才会去发起下⼀页的请求。取消掉scroll事件的监听,原本>4s的加载时间,控制在1s之内。
⼀些坑
1. 在开发者⼯具没有办法复现某些性能问题,是因为从逻辑层到webview的通讯,开发者⼯具底层是通过onpostMessage, ios好像是⾃⼰实现的桥接。所以强烈
建议使⽤真机进⾏调试
h5平台源码下载2. 开发者⼯具,没有办法在【network】⾥⾯看到图⽚资源的加载,通过【trace】⾯板连接安卓真机也没有办法看到。如果想测试懒加载的效果,就⽐较⿇烦,需要通过
设置开发者⼯具的代理到127.0.0.1,通过charles可以抓包看到
⼀些迷茫
搞⼩程序遇到的这些坑,虽然可以收获满满的填坑经验,但是这些填坑经验并不算是真正的计算机知识,因为这些知识的并不是基于对本质底层的理解,⽽是依靠经验,⽽
经验是很快就会过时,可能下⼀次⼩程序api来⼀次⼤的升级,⼩程序优化⼿段马上就会换成另外⼀种。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。