首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >京东购物小程序购物车性能优化实践

京东购物小程序购物车性能优化实践

作者头像
WecTeam
发布2020-02-19 15:13:24
2.6K0
发布2020-02-19 15:13:24
举报
文章被收录于专栏:WecTeamWecTeam

前言

作为京东购物小程序黄金流程之一,购物车汇聚了大量的营销玩法,页面内容丰富多样。页面节点树庞大、千变万化的特点,导致性能问题比较突出且优化难度较大。在纯技术角度的性能优化达到瓶颈之后,我们开始尝试基于业务进行性能优化。

Part 1 扫雷篇-分析性能问题

优化要点

  • 首屏时间:指用户打开页面到看到第一屏主要内容的时间
  • 渲染时间:指数据首次渲染或引起页面结构变化的渲染所花费的时间
  • 请求耗时:请求耗时越长,用户等待的时间越长
  • CPU 利用率:CPU 利用率达到饱和时容易导致页面白屏或闪退
  • 网络请求数:短时间发起太多请求会触发小程序并行请求的数量限制

分析工具

1、Performance monitor

它是小程序开发工具内置的一个可视化监控工具,能够在 OS 级别上实时记录系统资源的使用情况。

借助这个工具,可以监控 cpu 和内存占用量和波动情况,快速定位引起页面卡顿、机器发烫的模块,进而进行优化

Performances monitor

2、测试机

小程序性能分析工具较少,且开发工具的运行效果和真机差异较大,应尽量使用真机定位性能问题。

通常,我们使用 oppo r11 和 iphone 6s plus 等低档机排查性能问题,再分别挑选用户数占比较大的低、中、高档机器检验优化效果

3、监控系统

前端进行测速数据采集和上报,再通过监控系统分析页面的各项指标健康度,了解页面加载耗时情况,对性能优化有较大的参考价值。

监控系统

项目上线前,可以通过测试机检验优化效果,但测试数据毕竟不能反映用户实际情况。因此,像购物车这种,展示内容与用户强相关的页面,非常有必要使用监控系统辅助分析。

ps: 下文各项测速数据均来自监控系统。

分析过程

1、购物车业务分析

  • 商品信息复杂度高。一个商品需要展示的信息量,可能占据手机屏幕的四分之一、二分之一、一整屏,甚至超出一屏。
  • 商品归堆方式复杂。购物车商品普遍只需按照店铺归堆,但是京东的购物车在店铺归堆的基础上,还要按照促销活动归堆。

2、测速数据分析

购物车数据复杂度高,因此我们重点观察了商品总数与首屏渲染耗时的关系:

  • 首屏渲染耗时受商品总数影响。怀疑与分屏策略相关,分屏渲染的粒度应细化到商品层级,而非促销层级,从而降低促销活动对首屏渲染耗时的影响
  • 商品数量大于 10,首屏渲染耗时明显上涨。通过多次实验发现,首屏渲染的商品数<=5 时,首屏渲染耗时与空车渲染耗时非常接近,在同一梯度;当商品数>5 时,首屏渲染耗时会上升一个梯度。

结论:需进一步优化渲染策略,尽可能减少首屏渲染的商品数。

Part 2 实践篇-性能优化历程

自动分页渲染

背景

早期,为缩短白屏时间,购物车使用了分屏渲染技术,把数据分为首屏和非首屏两部分,首屏渲染完成后再渲染非首屏数据。 分屏渲染最大问题在于,一旦非首屏数据量过大,渲染耗时会很长,让用户等待很长时间,最糟的情况可能引起页面假死,严重影响用户体验。 随着业务增长,这个问题带来的影响已经越来越明显,因此我们开始考虑改用分页技术

1、技术选型

难点:

  • 业务复杂。短期内无法实现分页请求数据,只能实现纯前端分页
  • 数据量大。每个商品不仅包含主品的各项信息,还可能附加与商品结构类似的赠品、换购商品等
  • 商品列表顺序动态改变。例如修改商品促销,该商品可能由列表第一项变成最后一项,操作完成后还要定位到该商品

技术选型

综合考虑各种业务场景和各项分页技术的特点,最终决定采用自动分页渲染技术。

2、基本思想

  • 一次性请求全部数据
  • 将数据分成若干页,每次只渲染一页
  • 上一页渲染完成后,自动循环渲染下一页

3、循环渲染实现方案对比

  • 通过 setData 递归。setData 的回调函数触发时立刻渲染下一页。缺点是会导致 UI 线程一直忙碌,用户操作响应变慢。
  • 利用 setTimeout。setData 回调函数触发时,用 setTimeout 延迟一段时间再渲染下一页。缺点是执行时间不可控。
  • 利用时间分片。通过 requestAnimationFrame(简称 raf)实现。调用 raf 之后,浏览器在准备渲染下一帧前会调用你传给 raf 的回调函数。按照帧率为 60fps 来计算,每一帧的间隔在 16.6ms 左右。

通过多次实验对比,最终我们选择时间分片模式。

4、示例

Demo: https://developers.weixin.qq.com/s/XJEDb3mP7Kex

原理: 用 raf 代替定时器,每次 setData 完成后,延迟 16.6ms 左右,再渲染下一页

实现思路:每次 setData 时触发 wxs 事件监听器,在 wxs 事件处理函数中调用 raf,raf 回调执行时调用逻辑层函数渲染下一页

流程图如下:

raf demo 流程图

5、效果对比

下面是使用分屏渲染(左图)与自动分页渲染(右图)的效果图。可操作时间缩短 50%+

分屏渲染与自动分页渲染对比

移除 scroll-view

scroll-view 组件是一种滚动视图容器,它提供了一个名为 scroll-into-view 的功能,可以使视图滚动到指定元素,为方便描述,下文简称定位功能。

1、背景

购物车很多场景用到定位功能,小程序不支持 DOM 操作,使我们不得不使用 scroll-view 这个大型组件。

但是,scroll-view 组件存在较多性能问题:

  • 与 view 组件相比,scroll-view 占用内存和 cpu 资源更多。可通过 Performance monitor 观察 cpu、内存使用情况
  • 滚动体验比页面自带滚动效果差
  • 在一些低端机或页面节点总数较多的情况下,scroll-view 组件很容易引起掉帧、白屏

节点复杂度越大,总节点数越多,scroll-view 暴露的性能问题越明显。

为了优化滚动体验,减轻 cpu 和内存压力,我们移除了这个组件的引用。

2、难点

想要移除 scroll-view,必须找到定位功能的替代方案。在微信基础库版本 2.7.3 以上版本,可使用 wx.pageScrollTo 的定位到锚点功能,对于 2.7.3 以下版本,需要自己编码实现。

示例代码:

_pageScrollTo ({ partten }) {
    if (this.createSelectorQuery && wx.pageScrollTo) {
        const query = this.createSelectorQuery()
        query.selectViewport().scrollOffset()
        query.select(partten).fields({ rect: true })
        query.exec(function (res) {
            if(res) {
                const windowHeight = (wx.getSystemInfoSync() || {}).windowHeight || 619const offsetY = windowHeight * 0.35// 目标位置距离窗口上边界的偏移量const _scrollTop = res[0].scrollTop // 滚动条竖直滚动位置const _top = res[1].top // 目标节点上边界坐标const scrollTop = _scrollTop + _top - offsetY
                wx.pageScrollTo({ scrollTop, duration: 0 })
            }
        })
    }
}

建议关闭 wx.pageScrollTo 的滚动动画。在一些低端机器上,滚动过程中页面部分区域会白屏,且不会自动恢复。另外,基础库 2.6.4 以下版本,滚动过程中 fixed 元素会闪烁。

3、效果对比

移除 scroll-view 之后,列表滚动过程中几乎不会白屏。下面是 scoll-view 移除前后效果图。

滚动优化前后对比

数据预加载

指提前请求数据,打开页面后使用预请求的数据渲染

1、分类:

  • 跳转时预加载:即将发生页面跳转时请求数据
  • 预判预加载:预测用户从页面 A 进入页面 B 可能性大,在页 A 内主动请求页 B 的数据

2、跳转时预加载

跳转时预加载

目的:缩短白屏时间。从发生跳转动作,到目标页面 onLoad 触发,中间有一段时间间隔,利用这段空闲时间提前加载数据,可缩短白屏时间

原理:触发跳转操作后,在页面发生跳转前(即调用 wx.navigateTo 之前),调用目标页面的预加载处理函数,函数触发时开始发送请求。进入目标页面后,使用提前加载好的数据渲染页面

3、预判预加载

预判预加载

目的:提前加载目标页面请求,大幅缩短目标页面白屏时间。

原理:预测用户从页面 A 进入页面 B 的可能性较大,在页面 A 内主动调用页面 B 的预加载处理函数,提前加载请求。进入页面 B 后,使用预加载数据渲染首屏

缺点:

  • 对数据时效性要求较高的场景不适用
  • 预加载后,用户不一定会打开目标页面 B,可能造成资源浪费

4、效果对比

与页面 onLoad 执行才加载数据(即无预加载)相比,预判预加载首屏耗时缩短 40%,跳转时预加载首屏耗时缩短 27%。下面是无预加载(左图)与预判预加载(右图)效果图。

利用缓存

缓存是一种备受青睐的性能优化方法。不仅可以减少请求数,降低弱网场景空窗率,合理利用缓存甚至能使首屏耗时缩短至少 30%以上。

它适用于数据稳定性强,时效性要求低的场景,如图片、字体、配置文件等。

像购物车这种,商品列表变化比较频繁的场景能否使用缓存?

答案是肯定。

1、实现方法

实际上,购物车的数据结构比较复杂,数据量大,为避免引起性能问题,只会 setData 关键数据。但为了方便查找数据和逻辑运算,还维护了一份缓存数据,每次请求购物车接口都更新缓存。再次打开购物车页时,只要满足一定条件,就可以直接使用这份缓存数据渲染页面。

2、效果对比

缓存模式首屏时间比常规模式(页面 onLoad 时加载数据)快 44%,比预加载模式快 23%。下面是预加载模式(左图)与缓存模式(右图)效果图。

逻辑后移

指将部分前端业务逻辑移至后台。

1、意义

  • 减少前端代码量。对于大型小程序项目至关重要,不仅因为小程序代码包大小有限,若代码包过大,会直接影响小程序整体性能和页面切换速度
  • 利于多端统一。复杂业务由后台统一实现,前端仅做简单处理和展示,有效避免因各端开发对业务理解的差异,导致各端页面实际展现效果不一致
  • 降低人力成本。业务逻辑统一在后台实现,避免各前端重复开发。测试童鞋可重点关注后台逻辑准确性,无需分别对各端进行详细的业务逻辑验证
  • 增强项目可控性。与 h5 不同,小程序发版难度大、周期长、线上多版本并存,一旦出现紧急需求或业务问题,前端很难快速解决

终极目标:类似需求前端只开发一次,后期迭代由后端开发完成后直接上线。

2、改造过程

逻辑后移过程

参考规范:

  • 仅用于一处文案展示。仅用于在固定位置展示文案,没有其他模块用到相关数据,建议后台直接下发文案
  • 用于标识。用于标识某种类型、状态,建议将相同类型的字段合并为一个字段。
  • 用于复合场景。既要展示文案,又要用于其他业务逻辑计算。先看看相关模块是否可以一起改造,如若不能,建议后台下发关键数据,前端做简单文案拼接处理

总结

实际上,购物车页的数据加载和渲染采用了多策略组合方式,根据场景和当前机器环境的特点动态选择数据加载和渲染策略,目的是在保障用户刚需的同时为更多用户提供更极致的体验。例如某些场景使用缓存模式+自动分页渲染,而在一些兜底场景使用的是常规模式+触底渲染等等。

本文重点在于介绍购物车页性能优化的过程和思考,没有过多深入技术实现细节,希望大家阅读后能有一些新的想法。

参考文章

[1] 页面渲染机制与性能优化:https://segmentfault.com/a/1190000016458627

[2] 从浏览器多进程到 JS 单线程,JS 运行机制最全面的一次梳理:https://cloud.tencent.com/developer/article/1547827

[3] 高性能渲染十万条数据(时间分片):https://cloud.tencent.com/developer/article/1509390

[4] 前端性能优化之缓存利用:https://www.haorooms.com/post/cache_huancunliyong

[5] 再谈前端性能优化:https://www.cnblogs.com/cherryblossom/p/7866324.html

[6] 前端性能优化(超详细):https://www.jianshu.com/p/30c42b04623c

[7] https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame

[8] https://www.w3cplus.com/javascript/requestAnimationFrame.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WecTeam 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Part 1 扫雷篇-分析性能问题
    • 优化要点
      • 分析工具
        • 分析过程
        • Part 2 实践篇-性能优化历程
          • 自动分页渲染
            • 移除 scroll-view
              • 数据预加载
                • 利用缓存
                  • 逻辑后移
                  • 总结
                  • 参考文章
                  相关产品与服务
                  云开发 CloudBase
                  云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档