前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >性能翻倍!京东亿级体量小程序优化实践

性能翻倍!京东亿级体量小程序优化实践

作者头像
京东技术
发布2024-02-26 09:59:22
1460
发布2024-02-26 09:59:22
举报
文章被收录于专栏:京东技术京东技术

导读

本文深入探讨如何通过系统性的优化措施显著提升了京东亿级用户体量小程序的性能。从前端渲染优化等方面,技术团队实施了一系列创新策略,使小程序的性能翻倍。本文将详细介绍这些优化措施的实施过程和取得的成效,为在大规模用户基础上追求极致性能的开发者提供宝贵的实践经验。

01前言

在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!

小程序性能是指小程序在微信APP或者其他宿主APP中加载和呈现的速度,以及小程序对用户交互的响应程度。性能欠缺的小程序渲染和响应速度较慢,甚至会出现无法正常打开小程序的情况,在不同程度上极大地影响了用户体验,从而导致用户流失。

京东购物小程序随着更多业务不断的更新迭代,启动性能逐步下降,微信后台打开率仅86%,每天有几百万的流失。随着互联网人口红利的结束,增量变缓,如何通过技术手段提升启动性能成为重中之重,以便更好地留住来之不易的增量用户,进一步助力业务的成长。

02性能指标与衡量

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。

使用性能指标来评估小程序的加载速度是非常必要的,首先回顾一下京购小程序页面加载的几个关键阶段:

这几个关键阶段的含义如下:

阶段

含义

loadPackage

小程序代码包下载

First Paint(FP)

页面首次绘制

First Contentful Paint(FCP)

首次有内容的绘制

First Meaning Paint(FMP)

首次有意义的绘制

Largest Contentful Paint(LCP)

页面最大内容绘制,达到可交互状态

在以上的几个阶段当中,最注重的是用户从点击小程序开始到页面最大内容绘制 (LCP) 的总耗时。

而烛龙监控平台已经为京购小程序开发者们提供了性能监控指标,可以通过烛龙监控平台看到对应流程的耗时来作为衡量,小程序启动流程如图:

其中关键的几个监控指标字段和对应意义如下:

字段

意义

_perf_downloadPackage

代码包下载耗时

_perf_evaluateScript

逻辑层JS代码注入耗时

_perf_firstRender

页面首次渲染耗时

_perf_route

页面切换耗时

_perf_firstContentfulPaint

首次内容绘制时间(FCP)

_perf_appLaunch

小程序启动耗时

_perf_largestContentfulPaint

最大内容绘制时间(LCP)

烛龙监控平台根据以上几个指标权重和每个指标分值加权平均,计算用户体验值评分(UEI),如图:

03如何进行性能优化?

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。

3.1 代码包体积优化(减少小程序初始化耗时)

从上面的京购小程序启动流程图来看,在app.onLauch执行之前,主要耗时阶段为代码包下载代码注入。而代码包下载和代码注入的时长,均和小程序逻辑代码体积有关。一般而言,小程序代码包越大,逻辑层代码体积也越大,因此初始化耗时也更长。这里我们使用到以下技术:

3.1.1 独立分包

「独立分包」可以独立于主包和其他分包运行。从独立分包页面进入小程序时,不需要下载主包。

开发者可以按需将某些具有一定功能独立性的页面配置到独立分包中。当小程序从普通的分包页面启动时,需要首先下载主包;而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度。

针对于京购小程序首页,利用独立分包开发了京购极速版首页,并逐步投放在发现购物入口。通过和正常包对比,极速版首页的启动耗时总体降低了420ms,优化了14.5%的启动耗时,以上收益来自于Android侧的大盘优化效果。

3.1.2 分包异步化

「分包异步化」将小程序的分包从页面粒度细化到组件甚至文件粒度。这使得本来只能放在主包内页面的部分插件、组件和代码逻辑可以剥离到分包中,并在运行时异步加载,从而进一步降低启动所需的包大小和代码量。

分包异步化能有效解决主包大小过度膨胀的问题。

针对于附近生活圈频道页面,通过使用分包异步化将主包组件移至分包,将附近生活圈所占主包空间从126kb降低至39kb,极大地降低了主包代码体积;公共components,经过首页、购物车、我京等模块的共同努力,通过分包异步化从203kb瘦身到31kb;分类tab,通过分包异步化138kb瘦身到6kb。

3.1.3 分包预下载

在使用「分包加载」后,虽然能够显著提升小程序的启动速度,但是当用户在使用小程序过程中跳转到分包内页面时,需要等待分包下载完成后才能进入页面,造成页面切换的延迟,影响小程序的使用体验。分包预下载便是为了解决首次进入分包页面时的延迟问题而设计的。

值得注意的是,独立分包和分包预下载可以配合使用,对于独立分包,也可以预下载主包。

针对于附近生活圈频道页面将组件进行分包异步化引入之后,降低了附近生活圈频道各个楼层组件渲染的速度,因此通过在首页配置预下载分包组件的方式,通过提前下载附近生活圈分包组件,解决首次进入附近生活圈页面组件渲染延迟的问题。

3.2 代码注入优化

3.2.1 按需注入

可以通过小程序配置,有选择性地注入必要的组件代码:

代码语言:javascript
复制
{
  "lazyCodeLoading": "requiredComponents"
}

「按需注入」启用后,小程序仅注入当前访问页面所需的自定义组件和页面代码。未访问的页面、当前页面未声明的自定义组件不会被加载和初始化,对应代码文件将不被执行,以降低小程序的启动时间和运行时内存。

值得注意的是,插件包和扩展库目前暂不支持按需注入。如果需要实现插件按需加载,可以考虑将插件置于一个分包,并通过「分包异步化」的形式异步引入。

3.2.2 启动过程中减少同步API的调用

在小程序的启动过程中,会进行代码初始化并依次同步执行 App.onLaunch, App.onShow, Page.onLoad, Page.onShow 等生命周期函数,在此期间应尽量减少或不调用同步API。

常见的容易在初始化阶段调用的同步API有:

1、getSystemInfo/getSystemInfoSync,可尝试使用异步版本API getSystemInfoAsync代替;

2、getStorageSync/setStorageSync,应只用来进行数据的持久化存储,不应用于运行时的数据传递或全局状态管理。

3.3 首屏渲染优化

页面首屏渲染的优化,旨在让用户更早的看到有内容的页面绘制(FCP)或者有意义的页面绘制(FMP)。

3.3.1 避免引用未使用的自定义组件

在页面渲染阶段是,会初始化读取当前页面配置和全局配置中使用 usingComponents 引用的自定义组件,以及组件所依赖的其他自定义组件,引入未使用的自定义组件会影响页面初始化渲染耗时。

因此,当组件不被使用时,应及时从 usingComponents 中移除。

3.3.2 精简首屏数据

页面首次渲染的耗时与页面的复杂程度呈正相关。在京购小程序很多业务场景当中,小程序渲染的页面高度是超过一屏的,但在用户首次进入页面时,超出屏幕的页面内容并没有实际性的意义,因此只需要优先渲染出可视范围内的内容即可。当页面首屏渲染完毕后,再继续异步渲染剩下的页面内容。

因此可以对页面首次渲染的内容做一定的取舍,即:

1、如果页面从上到下是由多个独立的组件组合而成的,那么可以针对不在首屏范围内的组件进行延迟加载;

2、如果页面是由某个列表项展开构成的,例如首页的feeds流,那么可以通过主动控制列表项的长度进行分页加载,在滑动至接近于底部时再进行更多列表项的加载和渲染。

需要注意的是,与页面渲染无关的数据尽量不放在data当中,避免影响页面渲染耗时。

3.3.3 提前首屏数据请求

由于网络请求都需要一定的时间,但小程序页面渲染的数据却经常需要依赖服务端的接口返回,在服务端接口返回数据之前页面就可能是空白的或者骨架屏。

为了尽可能早发出核心数据请求,可以采用微信小程序提供的能力:数据预拉取。

「数据预拉取」使得可以在小程序启动时,由微信客户端通过微信后台提前向服务器拉取核心业务数据,当代码包加载完成时,在京购首页通过 wx.getBackgroundFetchData 拿到预拉取的数据,便可以更快地渲染出首页,减少用户等待时间,具体核心流程如图所示:

3.3.4 缓存请求数据用于初始渲染

除去上述的数据预拉取能力,微信小程序提供了 wx.setStorage、wx.getStorage 等API来进行本地缓存的读写。

在京购首页中,将上一次读取到的直出接口的数据存储在缓存当中,以便用户在下次初始化首页时,优先从缓存中读取首页直出数据用来快速渲染页面整体视图,待接口真实返回后再进行页面更新。

3.3.5 骨架屏

「骨架屏」用于页面渲染之前,通过一些灰色的区块大致勾勒出页面的轮廓占位,待页面数据加载完成后,再替换成真实的内容。骨架屏能够有效地避免页面在请求过程展示白屏,避免用户误以为加载失败而退出小程序;且能够避免不同楼层异步渲染的过程中上下跳动,影响用户体验。

3.4 发版更新频率等其他优化

3.4.1 合理规划版本发布

通过小程序更新机制可以得知,小程序在启动时如果检测到版本更新,会重新获取小程序的基础信息、重新生成初始渲染缓存等操作,从而影响页面启动耗时。过于频繁的发版更新频率可能会导致用户每次重新打开小程序都需要进行小程序的更新,使得平均启动耗时变长。

因此应提前做好版本规划,控制版本发布更新的频率。

3.4.2 优先使用本地版本设置

通过「优先使用本地版本设置」,判断某些较新的小程序版本无需强制用户更新到最新版本。可以在小程序管理后台「设置」-「功能设置」-「优先使用本地版本设置」进行设置,设置后,当用户使用小程序时,客户端会优先打开本地版本代码包。若用户本地版本不低于该版本,则优先使用本地版本,后台异步更新最新版本的代码包。若低于该版本,则优先更新到最新版本。

04总结和展望

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目

4.1 性能优化总结

看到这里,在了解了京购小程序的性能指标和启动流程后,已经能够很容易地从烛龙监控平台中,查看所负责业务对应的页面性能数据,及时发现页面的一些性能问题并及时进行优化。

当然,除去以上阐述的几点前端性能优化策略之外,也可以通过考虑与服务端约定新的数据格式,避免服务端传输无效数据导致响应内容体积过大等思路进行探索。

在经过上述多种优化后,从微信官方后台we分析中的数据可以看出,京东购物小程序的打开率从原先的86%提升到90%以上 ,相比优化之前每天减少近百万用户流失。

下图是内测阶段京东购物小程序优化前后的真机体验对比,从烛龙监控平台上看,首页整体冷启动耗时从4800ms左右降至2500ms以下。目前线上灰度过程中,用户随机50%命中优化后版本,后续会根据业务数据评估,逐步提高灰度比例,全面提高用户体验。

4.2 未来展望

基于当前在性能优化路上的探索和实践,结合实际线上的统计数据分析,在后续也仍会针对于「页面首次渲染」等耗时占比较大的流程进行深入的实践,在「渲染性能优化」层面做更多的尝试,从精简业务数据层面、尝试新的渲染引擎Skyline等等,为客户提供更加友好流畅的使用体验。

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

本文分享自 京东技术 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导读
  • 01 、前言
  • 02 、性能指标与衡量
  • 03 、如何进行性能优化?
  • 04 、总结和展望
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档