UniApp 小程序 JavaScript SDK 性能问题分析¶
本文介绍 @cloudcare/rum-uniapp 2.2.21 及以上版本采集的页面性能字段,以及如何据此识别首次渲染慢、页面退出前未渲染等白屏候选问题。
本文适用于 UniApp 小程序 JavaScript SDK,不适用于
GCUniPlugin-*原生模块。所有耗时字段上报到观测云后统一为纳秒(ns)。
采集范围¶
SDK 可以采集以下性能信号:
- 页面加载、
onReady、首次渲染、FP、FCP 和 LCP; - 页面退出前是否已触发
onReady或平台首次渲染信号; setData次数、累计耗时、最大耗时、排队耗时、更新耗时和合并次数;- 启动尝试、原生启动、脚本执行和代码包下载;
- 与慢页面关联的 Resource 和 Error 数据。
SDK 不采集屏幕截图,也无法判断业务骨架屏之后的核心内容是否可用。因此,任一性能字段缺失都不能直接等同于白屏。
平台性能数据¶
SDK 优先使用小程序平台提供的 Performance API。Observer 成功订阅后,performance_supported=true;平台同时提供可用首次渲染信号时,first_render_supported=true。
微信与兼容平台¶
微信格式的 entry 会直接映射到以下指标:
| Performance entry | RUM 字段 |
|---|---|
navigation.duration |
loading_time |
render:firstRender.duration |
first_render_time |
render:firstPaint.startTime - navigationStart |
page_fp |
render:firstContentfulPaint.startTime - navigationStart |
page_fcp |
render:largestContentfulPaint.startTime - navigationStart |
page_lcp |
冷启动的 appLaunch 与普通 route navigation 都可以建立首屏页面身份。SDK 会按 route、pageId 和最新 navigationStart 选择当前页面实例;paint 先于 navigation 到达时会暂存,避免把 entry 的绝对 startTime 错当成耗时。
抖音小程序¶
抖音使用 paint、evaluate、navigation、resource 和 launch entry。SDK 会先转换为统一口径:
| 抖音 entry | 统一口径 |
|---|---|
paint:first-paint |
page_fp、first_render_time |
paint:first-contentful-paint |
page_fcp |
paint:largest-contentful-paint |
page_lcp |
evaluate:app-service |
action_type=script_insert |
resource:miniprogram-package |
action_type=package_download |
抖音没有微信 firstRender entry,因此 SDK 使用当前页面 first-paint - navigationStart 作为该平台的首次渲染信号。该口径不等同于 FCP 或业务内容可用。
View 性能字段¶
能力与生命周期属性¶
| 字段 | 类型 | 说明 |
|---|---|---|
performance_supported |
boolean | 当前平台 Performance Observer 是否订阅成功 |
first_render_supported |
boolean | 当前平台是否存在 SDK 可用的首次渲染信号 |
view_start_reason |
string | page_load、page_show 或 session_renewal |
view_end_reason |
string | onHide、onUnload 或 session_renewal |
ready_reached |
boolean | 当前页面生命周期是否到达 onReady |
first_render_reached |
boolean | 当前页面是否已收到平台首次渲染信号 |
ended_before_ready |
boolean | page_load View 结束时是否仍未到达 onReady |
ended_before_render |
boolean | 支持首次渲染信号时,page_load View 是否在首次渲染前结束 |
view_is_active |
boolean | View 是否仍处于活动状态 |
ended_before_render 只在 first_render_supported=true 时有统计意义。Session 续期只拆分 RUM View,不代表页面重新加载,因此不会生成页面提前退出结论。
渲染耗时¶
| 字段 | 说明 |
|---|---|
loading_time |
页面 navigation 与生命周期观测到的最大加载耗时 |
page_ready_time |
View 开始到 onReady 的耗时 |
first_render_time |
微信 firstRender.duration;抖音为 first-paint - navigationStart |
page_fp |
FP 相对当前页面 navigationStart 的耗时 |
page_fcp |
FCP 相对当前页面 navigationStart 的耗时 |
page_lcp |
当前页面最近一次 LCP 相对 navigationStart 的耗时 |
first_render_data_transfer_time |
首次渲染初始化数据接收时间减发送时间 |
first_render_wait_time |
数据接收完成到视图层开始渲染的等待时间 |
first_render_view_layer_time |
视图层首次渲染耗时 |
first_paint_time 与 first_render_time 为兼容字段,均表示 SDK 选择的首次渲染信号;需要分析真实 FP 时使用 page_fp。
setData 耗时¶
| 字段 | 说明 |
|---|---|
view_setdata_count |
有效 setData 更新样本数 |
view_setdata_duration |
所有有效更新的累计耗时 |
view_setdata_max_duration |
单次更新最大耗时 |
view_setdata_pending_duration |
从进入队列到开始更新的累计等待耗时 |
view_setdata_update_duration |
从开始更新到结束的累计执行耗时 |
view_setdata_merged_count |
被平台合并处理的更新次数 |
SDK 会记录 listener 安装时的所属页面。隐藏页或旧组件的延迟回调不会计入当前 View,页面卸载或组件分离后会停止监听。
启动阶段指标¶
启动阶段以 action 数据上报:
action_type |
说明 |
|---|---|
launch_attempt |
首次 App.onLaunch 到达,每个 SDK 实例一次;不写 duration,并以 app_launch_attempt=true 作为有效 field |
launch |
平台 appLaunch navigation duration |
script_insert |
脚本执行耗时 |
package_download |
小程序代码包下载耗时 |
后三项依赖平台 Performance entry。建议使用 launch / launch_attempt 比例观察原生启动指标覆盖率,不要把缺少 entry 当成零耗时。
白屏候选统计¶
建议将白屏分析拆成覆盖率、慢渲染和提前退出三类指标。
统计样本¶
先筛选:
不支持首次渲染信号的平台应单独统计覆盖率,不进入 ended_before_render 分母。
推荐口径¶
| 问题 | 推荐条件 | 说明 |
|---|---|---|
| 慢首次渲染 | first_render_time 大于业务阈值 |
适合统计 P75、P95 与超阈值比例 |
| 退出前未首次渲染 | ended_before_render=true |
高置信度白屏候选,但用户主动快速返回也会命中 |
| 长时间未 Ready | page_ready_time 大于阈值 |
反映页面生命周期或初始化阻塞,不等同于视觉白屏 |
| 退出前未 Ready | ended_before_ready=true |
需要结合 view_end_reason 与停留时长排除快速离开 |
| FCP/LCP 慢 | page_fcp 或 page_lcp 大于阈值 |
更接近内容出现和主要内容稳定时间 |
推荐看板至少包含:
- Performance 与首次渲染信号覆盖率;
- FP、FCP、LCP、firstRender 的 P50、P75、P95;
ended_before_render、ended_before_ready比例;- 慢 View 的 Error、失败 Resource、
5xx和 TTFB 分布; - 按应用版本、平台、系统和设备型号拆分的趋势。
已知边界¶
- SDK 没有业务
markViewReady()API,不能确认核心业务内容已经可用; - Page
onLoad前发生的致命错误可能没有 View Context; - 当前不采集 Long Task、FPS、页面冻结和截图;
- 平台 Performance API、基础库与系统版本差异会影响字段覆盖率;
- 数据发送失败没有重试或本地持久化时,弱网环境可能低估问题比例。