五星门店小程序性能优化实践
一、背景介绍
1.1 业务介绍
五星门店小程序主要服务于五星线下门店交易场景,目前已有79个城市267家门店(包括超级体验店、城旗店、京东Mall等)在使用,用户可以通过小程序便捷地查看和购买门店的商品。五星门店小程序已实现基于Taro跨端解决方案的一码多端能力,一套代码可以在京东App以及微信小程序中运行,大幅提升了研发效率,可以更快更好地支持门店业务快速发展。
1.2 现状分析
随着业务高速发展,目前线下门店的数量仍然在不断扩张,未来会有更多的用户使用五星门店小程序。作为线下门店核心交易工具,为了能够更好得服务更多的门店和用户,快速了解一线的使用情况,给用户更好的体验,我们建立了以下机制:
(1)日常沟通群与门店导购和运营人员保持密切联系,及时获取用户反馈,为产研团队提供有价值的一线参考。
(2)我们还通过团队内部的日常体验走查机制,主动发现问题,并由产研侧推动优化小程序的体验性能。
无论是一线反馈还是内部走查,都为我们提供最真实、最有价值的问题参考,让我们能够从真实用户角度出发去优化小程序。
二、具体行动
2.1 结果概览
本次小程序优化主要集中在以下三方面:js报错率、页面渲染速度和包体积,整体优化结果如下所示:
(1)针对js报错率,优化前平均一周js错误数1374次,错误人数694人,优化后平均一周js错误数260次,错误人数129人,优化前后平均一周js错误人数和错误次数降低约81%。
(2)针对小程序黄金流程的页面渲染优化,不同机型在渲染速度上均有不同程度的提升,我们以iPhone14Pro、iphone14、onePlus9、华为Nova8以及红米手机五种测试机型作为参考:
(3)针对包体积优化,抽离主包中冗余的代码和页面,并且因商详页面访问人数和访问次数排在Top1,将商详页面从子包中移到主包,提升商详页面的访问速度,从而使得小程序日均切换耗时对比优化前下降17.95%,总包由5.92MB降低到5.32MB,缩小将近10.14%,主包由1.53MB缩小1.26MB,缩小将近17.65%。
2.2 实践分析
2.2.1 日常体验走查机制
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-15-24pcbfLjV0PJFqHfL.png)
通过以上的原则、标准和流程,可以有效地进行产品体验走查,提升产品的用户体验质量。自2023年以来,我们已完成:小程序整体流程场景、日常扫码进场体验场景、黄金流程体验场景、武汉扫码场景、首页升级体验场景、商详升级体验场景等6场体验走查,提出的数十个优化建议已经在优化迭代中落地。
2.2.2 日常优化迭代机制
针对大促备战紧张、日常需求复杂、量大、迭代快速的情况,我们与产品、测试等项目组成员商议后共同制定了日常优化迭代机制。自2022年以来,我们已完成48个版本体验优化。我们是如何与需求并行推动落地的呢?
(1)优化项来源收集:
1)前期主要通过用户动线梳理和业务说明,前端小组成员进行周会或日常走查并记录表格
2)后续扩大范围至项目组全体成员内部体验走查
3)大促期间与客服、用户、导购建立的线上和线下等体验沟通提升群组。
(2)确定走查范围:优先优化黄流页面,其次是其他访问人数较多、业务较重要的页面。
(3)确定走查方式:以视觉浏览、交互操作维度,多场景体验业务逻辑,来捕获问题。
(4)统计走查内容:根据错误严重程度排序,并组会同步产品、测试及其他相关人员,优先解决线上紧急重要优化项,其次进行日常版本迭代。
(5)严格按照日常项目流程开发和上线:利用项目外时间与业务、产品、测试等相关人员针对走查修复内容达成一致,最终共同进行排期、开发、测试、checkList和上线。
2.2.3 性能/质量优化
2.2.3.1 js异常报错解决
(1)统计报错信息,减少数据干扰因素,确定样本范围、报错范围、报错优先级
(2) 确定项目中JS报错的类型,进行迭代方式优化上线,并制定后续避免措施
2.2.3.2 缩包实践
(1)使用打包工具(webpackChain)来分析包体积的构成。
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-22DXc68jSuzN6tdby.png)
(2)优化大模块common(公共逻辑)及vendors(第三方库公共依赖)的步骤如下:
1)删除历史遗留无用模块。
2)整合和提炼组件及公共方法代码,删除重复代码。
3)按需引入第三方库,并在保证业务正常运转的前提下将第三方库替换为原生方法,若无法替代则使用体积最小版本。
4)静态资源优化:媒体资源较多的在本地存储或以Base64形式储存,本次调整为CDN引入。
(3)后续措施:
1)使用EOS平台检测代码重复率,及时整合和提炼代码。
2)独立引用第三方库,并使用最小体积版本。
3)优先统一使用CDN引入静态资源,尽量缩减存储在本地或使用Base64形式。
2.2.3.3 页面渲染速度优化
(1) 商详页面,经过优化后平均渲染速度提升约28%,左侧图均为优化后,右侧图均为优化前。
iPhone14:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-26Y6mh2JzhnyJ26T00.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-26N8HkVBW0NkRnfNG.gif)
对于商详切出小程序再切入小程序的情况,在优化之前,商详会重新刷新接口,导致页面会出现短暂抖动。在优化之后,商详保持原有数据不重新刷新接口,使得页面能够保持稳定
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-27ekmMrFTaU28sogb6.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-27B7sqj27OfvK7Hkol.gif)
One9Plus:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-299QSZKcBu6oe67ex.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-292JKTh2880hIkMiGA.gif)
红米:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-300lVftUBZXaJpONi.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-309IBYaxWXujtL28XF.gif)
分析商详现状: 页面滑动卡顿、首次进入商详白屏时间长、每次进入商详(无论是首次进入还是由上一级页面返回)都会请求商详接口,导致即使页面有数据也会有loading出现,并且在弹窗弹出的情况下,由上一级页面返回商详时弹窗会闪现一下等。
根据现状,从以下几个方面进行优化:
1)整体布局
优化前:商详页面最外层是 ScrollView 标签,借助ScrollY属性的设置实现页面滚动。经调研发现ScrollView更适合局部滚动,如果采用ScrollView实现页面级滚动,滚动性能会比较差,页面上下快速频繁滚动会卡顿。
优化后:去掉最外层的ScrollView标签,给最外层的View标签设置100%屏幕高度,内层元素高度由内容撑开,利用内容超出一屏高度产生的系统默认滚动特性实现页面滚动。滚动到某一指定位置由 scrollIntoView 更改为 Taro.pageScrollTo 实现(比如商详的返回顶部功能,切换顶部tab滚动到相应区域)。
2)组件优化
优化前:子组件直接在父组件中引用,并且组件中没有使用memo,useMemo,useCallBack等能提升性能的钩子函数。
优化后:合理使用React.memo, 商详页面比较复杂,子组件较多,父组件的渲染会导致子组件跟着一起渲染,React.memo可以做浅层比较,防止出现不必要的重复渲染。子组件使用CustomWrapper标签包裹,它可以将包裹的组件与页面隔离,子组件渲染时不会更新整个页面,由page.setData变为component.setData。
3)图片预加载
优化前:商详banner图片是进入页面之后从服务端请求回来的,有一定的延迟。
优化后:在小程序中,从调用 Taro.navigateTo 等路由跳转 API 到小程序页面触发 onLoad,中间会有一定延时(约300ms左右),此时利用Taro.preload在跳转前做一些预处理的逻辑,比如提前加载banner图片等,无需等待接口返回数据,提升商详页的banner渲染速度。
4)数据请求时机优化
优化前: 商详的数据请求逻辑在useDidShow中执行,每次进入商详(无论是首次进入还是上一级页面返回)都会调用接口,导致出现频繁的loading效果,并且弹窗弹出的时候会闪一下。
优化后:商详数据请求逻辑放在useEffect中,只有新进入商详会执行,由上一级页面返回商详时无需调用接口,减少了频繁的loading,大大提升了用户进入商详页的体验。
(2) 购物车页面,优化前后渲染速度平均提升约20%,左侧图均为优化后,右侧图均为优化前。
iPhone14:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-33Nq9ltTt33Eukz8Pi.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-3360H26OEJS28oiAT23.gif)
One9Plus:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-347NWp07TgHd64anX.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-340dDvYmf28oo70kln.gif)
红米:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-34jKBqHSoSIoth34QQ.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-3447P0Uhjke47ZuZqdr.gif)
购物车现状分析显示,购物车查车接口一次性返回全量数据,导致页面在商品数量超过30条时出现渲染慢和长时间白屏的问题,同时在操作购物车时也会出现卡顿等现象。为了解决上述问题,购物车优化主要集中在以下两点:
1)数据切割处理
优化前:全量数据直接传递给组件进行渲染,导致数据量大时渲染速度极慢。
优化后:原始数据切割成两部分,首先渲染前四条数据(大概能占满首屏),剩余数据利用setTimeout的特性进行异步处理,不会阻塞前四条数据的渲染,从而提升首屏的渲染速度。
2)调整父子组件之间数据传递的时机
优化前:父组件拿到原始数据之后直接传入子组件,在子组件内按照需要的数据结构进行处理。
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-35rQbMNsDzCPGbhns.png)
优化后:根据父组件优先子组件渲染的原则,将原始数据处理的部分移至父组件,将处理后的数据传递给子组件。自此,子组件在接收到数据后可以直接进行渲染,节省了原本用于子组件数据处理的时间,从而在一定程度上提升页面的渲染速度。
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-35q8I28BIDALczHTTK.png)
(3)结算页面,优化后渲染速度平均提升约25.4%。左侧图均为优化后,右侧图均为优化前。
iPhone14Pro:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-36X6kbMk8YgOQQFse.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-36pLPgdE28RG2H09qL.gif)
One9Plus:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-37ucxZAui7GBjcE37j.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-37XvHcKutE0iUrBU2.gif)
华为Nova8:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-38sKdDwgQ28OkGity8.gif)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-02-28-14-38ATv68mUgdCI0AVh.gif)
分析结算现状: 进入页面时,由于接口之间存在依赖关系,需要请求多个接口,导致页面渲染时间较长,并且在渲染完成后会出现页面抖动现象。根据现状,结算页的优化主要包括以下三点:
1)优化网络请求:
优化前:存在多个接口依赖,导致多次请求。
优化后:整合服务层接口,将多个接口合并为一个主接口,减少网络通信次数。
2)优化数据结构,减少setData使用频率:
优化前:接口过于分散,相互依赖,导致频繁的setData调用,降低性能。
优化后:接口整合后数据体量较大,采用递归方式将主体数据拆解,减少遍历过程,减少setData的使用频率,避免setData数据量变大,从而缩短页面的渲染耗时。
3)组件更新优化:
优化前:子组件直接在父组件中引用,且未使用CustomWrapper。
优化后:合理使用CustomWrapper,通过将子组件使用CustomWrapper标签包裹,实现子组件渲染时局部更新,由page.setData变为component.setData,减少全局更新,提高性能。
三、未来展望
以上是我们近一年来对五星门店小程序性能体验优化所做的一个阶段性成果的总结,整体性能得到显著提升。对于研发人员来说,提升用户体验是一项需要长期坚持的工作,作为技术同学,我们需要具备工匠精神,在接下来的一年中,我们将继续在小程序性能体验优化方面努力,给用户近乎原生应用的操做体验,主要会从以下几个方面入手:
(1)用户体验
(2)性能提升
(3)质量保障