背景
体验评分 Audits 是微信开发者工具内置的一项功能,会在小程序运行过程中实时检查,分析出一些可能导致体验不好的地方,并且定位出哪里有问题,以及给出一些优化建议。
京喜小程序作为京东战略级业务,拥有千万级别的流量入口,经过长时间的业务迭代,代码逻辑已经十分复杂臃肿,有迫切的性能优化需求。因此,结合体验评分功能,以京喜首页做试点,我们进行了一次体验评分的优化实践。目的是探索小程序体验评分的指标原则:拿到100分的小程序应该是什么样子的;同时希望借此给项目优化提供更多思路。
我会按照「了解首页评分现状,分析扣分项规则,解决扣分项」这个思路来介绍,就让我们开始吧~
京喜首页评分现状
打开小程序开发者工具-调试器-Audits,点击运行,操作页面滚一滚点一点,然后点击结束。
评分结果会根据评测页面内容差异、操作习惯、有无缓存有一定浮动,下图是京喜首页的一次评分:总分68,性能、体验、最佳实践都有扣分,合计8项扣分项,后面我们来逐条分析这些扣分项。
扣分项分析和优化
1、使用了过大的 WXML 节点数目
得分标准:页面 WXML 节点少于 1000 个,节点树深度少于 30 层,子节点数不大于 60 个。
页面节点指标的意义在于,过大的节点数,过多过深的节点组成,都会增加内存使用,样式重排时间更长,影响体验。
现有节点2500+,想要进行优化,首先需要了解页面各个模块的节点数分布。
如何统计每个模块的节点数呢?可以使用「控制变量法」,利用性能评测工具中,节点数超过1000时会列出节点总数的能力,我们可以在总指标超过1000的情况下,每次隐藏一个模块:
目标模块节点数 = 原总节点数 - 当前节点数
(实测节点数会有小范围浮动,可以测3次取平均值)
首页的模块分析图如下:
(第一屏) (第二屏)
简化数据如下:
观察列表可以得到两个信息:首页分为展示状态互斥的第一屏和第二屏;列表模块的节点数是大头。
因此,我们得到优化的两个方向:
- 页面元素按需加载,不展示时不渲染
- 长列表减少元素个数
第一个优化项可以通过变量控制组件显示隐藏,按需加载卸载。
第二个优化项首先想到的是减少列表接口分页数值,比如一次请求20条数据改为请求5条。但是如果接口不支持自定义分页,还可以实现更小的分页拉取吗?
那就自己写一个分页方法的代理吧~
思路如下:
上方为原始请求,每次20条数据,下方为代理请求的实现,每次返回5条。灰色虚线框是真实的请求数据动作,通过维护一个全量数据,需要哪页取哪页,这是示例代码:
通过以上两个优化,可以成功的把首页的页面节点数瘦身一下了,最后我们成功达到 wxml 节点总数不大于1000的目标。
2、存在图片太大而有效显示区域较小
得分标准:图片宽高乘积 <= 实际显示宽高乘积 * (设备像素比 ^ 2)
简单理解是图片尺寸太大而展示尺寸太小,导致浪费网络请求时间和内存资源。
解决方案:cdn服务商一般都支持通过参数获取不同尺寸的图片,前端可以包装一个公共方法,根据页面元素尺寸拉取合适大小的图片。
此外,补充一下图片体积的内容,除了关注图片尺寸,具体的体积大小其实更值得关注,有以下两个点可以了解下:
- 图片类型的选择大有文章,jpg/png/gif 还有 webp 应该怎么选呢?先放一张 google 的图
- 利用一些压缩技术对图片进行压缩,png 推荐 https://tinypng.com/ ,压缩尺寸可观,但对图片显示质量影响甚微。
3、存在可点击元素的响应区域过小
得分标准:可点击元素的宽高都不小于 20px
移动端操作全靠手指,过小的交互区域会带来不好的体验,可以通过增大元素响应热区的方式来优化,以下方式都可以:
padding
- 透明的
border
box-shadow
4、对网络请求做必要的缓存
得分标准:3 分钟以内同一个url请求不出现两次回包大于 128KB 且一模一样的内容
这一项的理由是,发起网络请求总会让用户等待,可能造成不好的体验,应尽量避免多余的请求,比如对同样的请求进行缓存。
优化方式:
- 善用小程序的 storage 能力,做好更新和过期管理后,尽可能缓存请求到的数据。
- 针对确实需要多次请求的日志类接口,可以通过在参数内添加随机数或者时间戳的方式进行区分,避免误判。
5、存在短时间内发起太多的请求
得分标准:通过wx.request
发起的耗时超过 300ms 的请求并发数不超过 10 个。
不同于上一项,这一项关注的是接口并发数:
wx.request
(HTTP 连接)的最大并发限制是 10 个wx.connectSocket
(WebSocket 连接)的最大并发限制是 5 个
优化方式:
- 计算逻辑后移, 接口聚合
- 对于职责类似的网络请求,最好采用节流的方式,先在一定时间间隔内收集数据,再合并到一个请求体中发送给服务端
6、存在未绑定在wxml上的变量
得分标准:setData
传入的所有数据都在模板渲染中有相关依赖
这一项考察的是 data 冗余的问题,小程序设计了渲染和逻辑分离的双线程,两边通讯通过 evaluateJavascript
转换字符串再进行拼接实现,需要非常小心两个线程之间通讯的数据量。因此,未绑定wxml的变量,最好优化成不使用 setData
。
根据使用场景,可以做的优化有:
- 与页面展示无关的内部变量,可以挂载在组件实例上,比如维护一个
this.privateData
对象 - 使用小程序新版本支持的「纯数据字段」:该字段不会被传递到 wxml 内,配置正则划定它的匹配范围,可以正常使用
setData
方法,具体用法参见文档:https://developers.weixin.qq....
但是,如果你像我一样遇到上面策略无法覆盖的场景呢?
- 需要修改旧代码,配置纯数据字段的正则影响太大
- 京喜首页使用了 Taro 做多端适配,Taro 编译复杂逻辑的数组后会出现「影子变量」去代理逻辑,原本的数组变量被架空导致扣分
那么还有一个终极 hack 的方法:
这样 list 会被判断为有绑定节点,就不会扣分了
7、发起太多的图片请求
得分标准:同域名耗时超过 100ms 的图片请求并发数不超过 20 个
最后这一项也是图片相关,发起太多图片请求会触发浏览器并行加载的限制,可能导致图片加载慢,用户一直处于等待中。
优化方式:
- 雪碧图
- 图片懒加载:小程序
Image
组件支持通过配置lazy-load
参数来实现懒加载(https://developers.weixin.qq.... ),具体判定逻辑是图片进入上下三屏就开始加载。如果需要更可控的实现,可以自己构建组件来处理。
总结
做完这些优化,再测一下体验评分:
以上就是京喜首页在小程序体验评分优化方面进行的实践内容了。
总结一下,小程序性能评分可以从指标和实际数据上给我们的项目优化提供一些建议,本文主要从评分角度去分析了各种优化可能,希望能为各位小程序开发者带来参考价值。
参考资料
[1] 小程序开发文档:https://developers.weixin.qq....
[2] Images: Your easiest page speed win: https://searchengineland.com/...
[3] Tiny Png: https://tinypng.com/
欢迎关注凹凸实验室博客:aotu.io
或者关注凹凸实验室公众号(AOTULabs),不定时推送文章。