此前综合篇中有提到,“对于独立性较强的页面可以通过独立分包的方式提升启动速度”。实践过程中,腾讯课堂小程序是如何分析问题并利用独立分包进行优化的呢?又如何得知生产环境下从某个页面启动的耗时,对优化效果加以验证呢?本篇文章将一一道来。
一、背景
当前环境下,微信小程序成为了重要的活动运营渠道。为了满足页面高效率在小程序端、H5、App 端上线和迭代的需求,大量运营和活动页面在小程序端选择了 Webview 中内嵌 H5 的形式。因此,腾讯课堂小程序实现了 common-act 页面(common-act为小程序页面名称)作为通用的小程序 Webview 承载页。
此页面先后承载了赠一得一、堂豆福利社(后迭代升级为 kbone 架构)、拉新红包、春节活动、三月大促等 20 系列活动页面在微信小程序端的运营。
由于大部分活动都是线上运营 ,用户从主站跳转打开活动页时页面加载时长问题不明显。但在薪选活动的线下运营中,用户主要通过扫描小程序码启动小程序并打开活动页,整个启动和加载的过程的耗时问题十分凸显,迫切需要对通用活动页面的启动速度进行优化。
经过对小程序启动过程的分析,以及此 Webview 页面较少依赖小程序公共方法和公共组件的特点,选择了对页面拆分独立分包的方式进行优化。活动页的独立分包相比于主包体积减小了 93%。经过小程序性能测速监控对比发现,优化后用户启动页面的速度总体提升了 30%,高端机平均可以在 1s 内启动 common-act 页面。
二、小程序活动页启动过程分析
2.1 common-act 页面是如何打开H5的
作为承载 H5 的通用小程序页,commmon-act 负责处理不同形式的入参,得到业务需要的完整 url,并以 query 的形式向 web 页面注入用户票据。
可以看到打开页面的整个过程是串行的,用户需要先从 common-act 页面启动小程序,页面 onLoad 阶段会通过参数生成 H5 链接并通过 setData 传输给视图层的 webview
组件。在页面参数中已包含页面地址(不用从配置平台换取 url)的情况下,整个打开的过程约为 小程序启动时长 H5 加载时长。
2.2 common-act 活动页启动的各阶段
common-act 页面的整个启动过程可大致分为加载小程序和加载 H5 两个过程。
小程序加载指:用户点击小程序卡片/扫码/点击其他跳转链接呼起小程序到首屏 onReady 生命周期。
H5 加载指:Webview 中开始准备打开新的 web 页面(navigationStart)到页面首屏的时间。完整过程的各个阶段及对应页面表现如下。
本文对小程序活动页的优化实际上指的是对“小程序加载”的过程进行优化。
2.3 微信小程序启动和加载过程
根据微信官方文档,微信小程序启动过程包括以下几个部分:
- 小程序资源准备
- 代码注入
- 首页渲染
其中资源准备可以划分为小程序环境准备和代码包准备两个阶段。
在启动流程中,小程序代码包准备、开发者代码注入和首页渲染是与开发者相关的,开发者可以进行一定的优化工作。其他部分目前开发者暂时无法干预。
三、小程序活动页启动时长优化方案
3.1 小程序活动页启动现状
通过小程序管理后台启动数据可知,5 月首周,小程序整体在全量更新情况下平均启动数据如图所示
全部机型 | 低端机型 | |
---|---|---|
下载代码包 | 600ms | 1000ms |
代码注入 | 270ms | 700ms |
初次渲染 | 170ms | 400ms |
总耗时 | 3900ms | 7800ms |
但现阶段小程序管理后台缺少从不同页面启动的具体数据。
common-act 页面目前是普通分包,代码包准备和代码注入阶段都执行了完整的主包。在加载和处理主包的过程中由于同步准备了很多核心页面依赖的基础信息和公共方法,耗时较长。但大部分的主包内容在活动页逻辑中是不依赖的。
因此可以从此角度进行优化。如果只下载、注入活动页需要的代码包将极大降低代码包准备和代码注入的时长。对于启动速度提升效果将比较明显。
3.2 独立分包方案
独立分包是小程序中的特殊分包,可独立于主包和其他分包运行。从独立分包启动小程序时,不需要同步准备主包(从普通分包页面启动小程序需完整加载主包)。等用户进入普通分包或主包内页面时,主包才会被下载和解析。因此可以提高小程序的加载速度。(文档可见:独立分包)
由于独立分包中不能依赖主包和其他分包中的内容,相关依赖需要全部位于页面文件夹中,分析页面涉及的公共依赖包括:
- 基础npm包依赖:@tencent/imwxutils(封装了一些小程序基础方法)、@tencent/imlog-wx(用来做日志上报)、simple-base-converter(用于压缩参数长度)
- 登陆相关:判断登陆态、获取小程序登陆票据
- 路由相关:页面跳转
- 请求相关:keFetch (业务侧封装的请求方法)
以上涉及容器页基础能力的依赖需要整理出来放到页面文件夹下,页面文件目录如下:
代码语言:javascript复制common-act/
├── common-act.css
├── common-act.json
├── common-act.ts
├── common-act.wxml
├── node_modules/...
├── package-lock.json
├── package.json
└── utils
├── const.ts
├── fn.ts
├── index.ts
├── performance.ts
└── type.ts
经过独立分包处理后,构建产物中 common-act 页面独立分包大小为 134.92KB,相比于主包体积减少了 93%。
3.3 小程序性能测速上报方案
页面启动速度的优化需要有比较详细的启动数据作为依据,当前管理后台的性能数据还无法满足页面启动速度监控的需要。小程序 performance API 可以返回以下性能指标:
- 启动时长:小程序启动的时间,仅在启动页面抛出
- 代码注入时长:主包、分包注入时抛出
- 页面首次渲染时长:页面首屏渲染时长,页面打开时抛出
- 路由时长:页面跳转时抛出
其余可能影响启动速度的因素和对应需要上报的数据包括:
- 通过 getSystemInfo 返回机型、基础库信息
- 通过 getNetworkType 返回网络类型、信号强度
- 通过 getAccountInfoSync 返回小程序版本号
- 同时上报页面路径和页面参数作为日志分析的参考信息
基于这些数据,imlog 日志上报字段如下
project | message | cmd | pathname | cost_time | addition | platform | query |
---|---|---|---|---|---|---|---|
weapp-ke | performance |
- 通过 project 和 message 字段能定位到小程序性能上报数据
- cmd 的值可能为 appLaunch、firstRender、route、evaluateSript
- pathname 标识性能记录产生的页面,如 pages/common-act/common-act
- cost_time 表示此次 cmd 表示行为的耗时
- addtion 记录了此次性能记录的其他相关信息,包括此次行为开始时间 startTime、机型、微信版本、基础库版本、网络类型、信号强度。(由于 firstRender、evaluateSript 记录在启动和页面跳转时都会产生,addtion 中用 isLaunch 标识此条上报是启动时的行为记录。)
- platform 包含小程序正式版版本信息。用于比较不同发布版本的表现。
- query 为页面参数,用于附加判断页面信息。
四、独立分包优化效果分析
提前发布包含数据上报能力的版本收集当前的表现数据后,通过 50% 灰度发布独立分包的版本,一段时间内收集到通用活动页面的启动时长上报数据共 38107 条。数据清洗:删除启动时长为异常值(负数、非数值记录、数值异常大)的记录共 447 条。剩余有效数据 37660 条。其中:
- 旧版小程序(未独立分包)上报记录 17692 条
- 新版小程序(独立分包)上报记录 19968 条
4.1 未独立分包启动数据分析
旧版小程序(未独立分包)从 common-act 启动的启动时长数据共 17692 条。数据概况如表格所示。
最小值 | 最大值 | 平均值 | 中位数 | 平均差 |
---|---|---|---|---|
259 | 19971 | 4008 | 3231 | 1940 |
以 1000ms 为间隔,分析启动时长数据在 0-20000ms 的分布,统计数据如下:
频率分布直方图和频率累积曲线如图所示:
可以发现,启动时长主要分布在 2000-4000ms 之间,此区间的比例超过 47%。44% 左右的用户启动行为可以在 3000ms 以内启动小程序。
4.2 独立分包启动数据分析
新版小程序(独立分包)从 common-act 启动的启动时长数据共19968条。数据概况如表格所示。
最小值 | 最大值 | 平均值 | 中位数 | 平均差 |
---|---|---|---|---|
129 | 19989 | 2942 | 2259 | 1542 |
以 1000ms 为间隔,分析启动时长数据在 0-20000ms 的分布,统计数据如下:
频率分布直方图和频率累积曲线如图所示:
可以发现,启动时长主要分布在 1000-3000ms 之间,此区间的比例超过 59%。70% 左右的用户启动行为可以在 3000ms 以内启动小程序。
4.3 对比分析独立分包优化结果
平均值 | 中位数 | 平均差 | |
---|---|---|---|
非独立分包 | 4008 | 3231 | 1940 |
独立分包 | 2942 | 2259 | 1542 |
- 平均启动时长减少 1066ms,提升 26.59%。
- 启动时长中位数减少 972ms,提升 30%。
- 平均差减小说明启动速度更集中在平均值附近,即长尾数据更少。
- 根据频率分布数据,3000ms 以内完成启动的用户启动行为比例由 44% 提升至 70%。
4.4 弱网环境下的启动优化程度
由于 2G、3G 的上报数据太少,总和低于 200 条,不太具有分析价值。
4.5 机型对启动优化程度的影响
按照微信小程序官方对高中端机的分类如下:
- iOS高端机:iPhone X、iPhone 11、iPhone 8 系列
平均值 | 中位数 | |
---|---|---|
非独立分包(ms) | 1804 | 1331 |
独立分包(ms) | 987 | 816 |
提升时间(ms) | 817 | 515 |
提升比例 | 45.2% | 38.6% |
- iOS中端机:iPhone 7系列
平均值 | 中位数 | |
---|---|---|
非独立分包(ms) | 2712 | 2255 |
独立分包(ms) | 1686 | 1440 |
提升时间(ms) | 1026 | 815 |
提升比例 | 37.8% | 36.1% |
- iOS低端机:iPhone 6s、iPhone 6系列
平均值 | 中位数 | |
---|---|---|
非独立分包(ms) | 4440 | 3483 |
独立分包(ms) | 3136 | 2522 |
提升时间(ms) | 1304 | 961 |
提升比例 | 29.3% | 27.6% |
- 安卓高端机:OPPO R17、VIVO X27、HUAWEI P30系列
平均值 | 中位数 | |
---|---|---|
非独立分包(ms) | 3335 | 3099 |
独立分包(ms) | 2348 | 2135 |
提升时间(ms) | 987 | 964 |
提升比例 | 29.6% | 31.1% |
- 安卓中端机:OPPO R15、OPPO A9、VIVO X21、VIVO Y97、荣耀8X系列
平均值 | 中位数 | |
---|---|---|
非独立分包(ms) | 4853 | 4337 |
独立分包(ms) | 3945 | 3303 |
提升时间(ms) | 908 | 1034 |
提升比例 | 18.7% | 23.8% |
- 安卓低端机:OPPO A5、OPPO A57、VIVO X9、VIVO Y93系列
平均值 | 中位数 | |
---|---|---|
非独立分包(ms) | 7560 | 6509 |
独立分包(ms) | 6298 | 5146 |
提升时间(ms) | 1262 | 1363 |
提升比例 | 16.7% | 20.9% |
可以看到机型对小程序启动速度和优化效果有很大的影响。iOS 高、中端机型,安卓高端机型优化后启动时间总体在 2s 以内。
【此微信官方标准未涵盖2019年后的机型,新机型实际表现会比旧机型更优】
从优化效果上看,低端机的启动时长在绝对数值上减少的更多。但由于高端机在小程序环境准备、代码注入、页面渲染的时间更短,独立分包提升比例更大。低端机相对而言独立分包提升比例更有限一些。
五、优化总结
- common-act 独立分包的优化方案对小程序 common-act 页启动的提升效果较明显,总体上看,启动时长的中位数由 3.2s 减少至 2.2s(高端机总体启动速度 1s 内),从活动页启动速度提升 30%。
- 采用独立分包后,common-act 页面启动长时间等待的比例明显下降,3s 内完成启动的用户比例由 44% 提升至 70%。对用户体验提升明显。
- 小程序启动速度的主要影响因素为用户的移动设备性能,性能好的机型平均启动时长小于 1s。
- 启动过程中,开发者仅能够从代码层面影响代码包准备和代码注入的时长。其余微信底层的环境准备和处理时长对整体启动时长的影响更大,且直接依赖于用户的设备性能和网络情况,开发者可以优化的空间有限。
这是腾讯课堂小程序优化的第三篇专项优化文章,前两篇文章:
1. 《腾讯课堂小程序性能极致优化——综合篇》
2. 《腾讯课堂小程序性能极致优化——网络请求优化篇》
都收获了满满好评,欢迎大家讨论交流~
紧追技术前沿,深挖专业领域
扫码关注我们吧!