微信小程序性能二三事
29 October 2017

小程序代码在ios上很溜,但是安卓机上性能问题很多,低端安卓机对性能调优更是要求贼高,稍不注意,页面就能卡死。

性能问题基本都是cpu不够用导致的卡顿,这种卡顿可能是1)dom太大,内存爆满 2)js操作频繁,js进程繁忙 3)渲染问题,可能是被js阻塞了,也有可能是所在环境的渲染机制不够优化

在本次为小程序开发的双十一会场页面时,总结出以下经验

存在的性能问题及解决方案

在开发中发现在低端机上几个小程序端需要注意的事:

  1. dom大了后,bindtap事件会不灵敏,短时间连续触发的bindtap事件后续的会丢失。原生小程序测试时,3000个dom节点就有丢失现象。后来尝试了使用touchstart和touchend去模拟,发现虽然touchstart很灵敏,但是touchend会丢失(个人猜测小程序的tap事件也是通过touchstart和touchend模拟的)。我们的大促会场600个商品时我算了下大约13000个dom节点,低端安卓机事件丢的很严重,间隔几乎是秒级别才能触发下一次事件。所以解决方案只能减小dom量,添加dom懒加载和动态移除的逻辑,经过多次测试,比较理想的效果是预加载2屏

2)滚动时setState卡顿严重,如果滚动时有触发setState操作,那么setState成功可能发生在几秒后,即使滚动操作在几百ms内就结束了。这就导致导航类功能的滚动跟随效果在安卓机上反应特别慢,滚停到某个商品楼层后,过了1-2s才导航条才突然动一下,所以最终取消了安卓的滚动跟随效果。(不根据版本取消效果,是因为发现即使是安卓最新的7.1版本在性能不好的机器上也会这样)

3)白屏问题

快速疯狂滚动页面,前面的页面没渲染出就不停的往后滚,发现小程序不是优先渲染可视区域,而是一定要把曾经滚过的区域按顺序渲染了。所以如果快速疯狂滚动,后面的内容白屏等待时间会很久。考虑到正常用户不会有这种需求,想看后面的内容可以通过楼层导航过去,而且这个问题我们也找不到解决方案,所以这个现象没有处理。

注意事项

1)懒加载+动态移除非可视范围内的内容,让dom小下去

2)耗时的js操作异步化,不要阻塞主线程。落地一点说,小程序里不要做频繁的setState操作,不在state里放跟视图层无关的内容。譬如我之前为了代码清晰,把导航功能模块里的楼层位置信息放到了视图层也用的一个变量里,其实视图层并不直接用到这个信息,这个信息为了准确,又会在每次滚动后重新计算,导致频繁setState,且set的是跟视图层无关的数据,优化后,性能提升很明显。

3)还有跟小程序本身相关的,wx.createSelectorQuery系列接口都是异步的,会受主进程影响,如果主进程繁忙,这个接口返回时间会延迟很久也是s级别的,对于楼层导航和懒加载这种需要页面各模块位置信息的功能,不能每次操作都等这个接口返回,可以缓存数据,取缓存,然后用户的操作触发调接口更新缓存,在缓存有更新时,为了更准确,也可以主动触发下需要位置信息的后续处理函数。

4)少用scroll-view,这个组件对性能影响实在太大,单纯的只是需要一块可滚动区域,请用css+view解决

5)不知道微信的小程序做了什么,滚动操作时进程异常繁忙,滚动停止后很久才是可操作和执行js状态,所以尽量少的触发在滚动时的回调函数,节流函数必须合理用起来。

性能调优是个漫长的取舍过程,需要不断测试来获取最优效果。cpu只有那么多,一段时间只能干那么多事,那就要干效果最好最重要的事。