性能翻倍!京东亿级体量小程序优化实践 | 京东云技术团队

京东云开发者
• 阅读 174

一、前言

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

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

二、性能指标与衡量

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

性能翻倍!京东亿级体量小程序优化实践 | 京东云技术团队

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

阶段 含义
loadPackage 小程序代码包下载
First Paint (FP) 页面首次绘制
First Contentful Paint (FCP) 首次有内容的绘制
First Meaningful 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),如图:

性能翻倍!京东亿级体量小程序优化实践 | 京东云技术团队

三、如何进行性能优化

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 按需注入

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

{
  "lazyCodeLoading": "requiredComponents"
}

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

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

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

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

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

  1. getSystemInfo/getSystemInfoSync,可尝试使用异步版本APIgetSystemInfoAsync代替;

  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.setStoragewx.getStorage等API来进行本地缓存的读写。

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

3.3.5 骨架屏

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

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

3.4.1 合理规划版本发布

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

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

3.4.2 优先使用本地版本设置

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

四、总结和展望

4.1 性能优化总结

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

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

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

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

性能翻倍!京东亿级体量小程序优化实践 | 京东云技术团队

4.2 未来展望

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

作者:京东零售 黄宏峰

来源:京东云开发者社区 转载请注明来源

点赞
收藏
评论区
推荐文章
小森森 小森森
1年前
计划助手V1.0-微信小程序(QQ小程序)-源代码分享
疫情期间在家感觉好无聊啊,于是利用空闲时间做了一个用来记录和管理小目标时间的小程序,命名为《小沙漏》。QQ版本小程序同步上线,QQ小程序叫《时间小沙漏》,欢迎大家前来体验,后期也会添加其他的新功能哦【区别】:微信小程序的代码与QQ小程序的源码是不一样的。微信小程序的源码基于微信小程序云开发,需要在有网络的情况下使用,具有同步功能,所有记录在删除小
CuterCorley CuterCorley
3年前
uni-app入门教程(7)第三方登录和分享
前言本文主要介绍了APP开发的两大基本功能,即第三方登录登录和分享:包括登录通用配置,微信小程序和APP的第三方登录方式,和分享到聊天和朋友圈,使用uniapp实现有不同的接口和实现方式。一、通用配置因为小程序和APP登录接口不同,需要在前端进行跨端兼容处理,同时微信等平台的小程序一般只支持所属宿主程序的第三方登录,而无法包括其他的
她左右 她左右
3年前
uni-app - 实现热更新及时提醒用户更新
1.原因分析在小程序更新开发版本之后,用户本地并没有对之前版本的小程序进行删除,那么再进入小程序的时候的版本是不会发生变化的,这是由于发版是异步执行,因此新版本将会覆盖的比较慢,本质是小程序的启动方式分为两种,冷启动与热启动。冷启动:指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。热启动:指用户已经打开过某
Stella981 Stella981
2年前
App唤起微信小程序和回调
在同一开放平台账号下的移动应用及小程序无需关联即可完成跳转,非同一开放平台账号下的小程序需与移动应用(APP)成功关联后才支持跳转。可在“管理中心移动应用应用详情关联小程序信息”,为通过审核的移动应用发起关联小程序操作。唤起App打开下程序他有两种方式:1,通过App分享小程序卡片到微信,然后在微信上点击小程序卡片打开小程序,
Easter79 Easter79
2年前
Taro小程序自定义顶部导航栏
微信自带的顶部导航栏是无法支持自定义icon和增加元素的,在开发小程序的时候自带的根本满足不了需求,分享一个封装好的组件,支持自定义icon、扩展dom,适配安卓、ios、h5,全面屏。我用的是京东的Taro多端编译框架写的小程序,原生的也可以适用,用到的微信/taro的api做调整就行,实现效果如下。!在这里插入图片描述(https://i
Wesley13 Wesley13
2年前
APP-H5- 小程序区别 (转载)
APP、H5、小程序区别●运行环境原生App直接运行在操作系统的单独进行中(安卓中可以开启多进程),而小程序运行环境是微信开发团队基于浏览器内核完全重构的一个内置解析器,针对性做了优化,配合自已定义的开发语言标准,提升了小程序的性能。是一种应用,并非完整的浏览器,只用到一部分H5技术,无法调用window对象和docu
Stella981 Stella981
2年前
2021年前端还有前景吗?
或许很多刚刚入门前端的同学都会思考:2021年前端还有前景吗?随着微信小程序的普及,以及app的下载,留给网页端的空间会越来越小吗?大公司固然无所谓,可是对于小公司与其耗费精力做网页,还不如开个公众号小程序。所以学前端会有未来吗?其实前端绝不仅仅是网页开发而已。微信小程序和App,其实都离不开前端范畴。尤其是微信小程序,几乎就是前端垄断的世
京东云开发者 京东云开发者
6个月前
京东小程序平台助力快送实现跨端 | 京东云技术团队
前言:京东小程序开放平台是由京东自主研发的开发者开放平台,类似于微信和支付宝的小程序开放平台,提供了丰富的开放能力和完整的小程序开发生命周期所需的功能。开发者可以轻松地使用开发者工具IDE进行开发、调试、预览和代码转换,并在控制台进行线上小程序发布、审核、
笑面虎 笑面虎
4个月前
【15章】前端高手特训 从0到1带你手写一个微信小程序底层框架
【15章】前端高手特训从0到1带你手写一个微信小程序底层框架视频课程分享——前端高手特训从0到1带你手写一个微信小程序底层框架,课程包更新,附源码。大家下载学习。微信小程序实质上是一款基于web技术的应用程序,他和我们平常所接触到的前端网页是大同小异的。相
京东云开发者 京东云开发者
4个月前
【最佳实践】京东小程序-LBS业务场景的性能提升 | 京东云技术团队
一、前言1.1京东LBS门详业务介绍京东LBS门详目前已经支持了仓网、药急送、天选、小时达POP多种业务,并且具备了多端的能力,一套代码可以在京东app、健康app、微信小程序中运行,一定程度上研发效率的提升能够更加快速的支持业务迭代。随着业务需求猛增、各