跳转至

Web 页面性能与用户体验分析


Web RUM SDK 会把真实用户访问页面时的加载、渲染、交互、布局变化、错误、资源和长任务数据关联到同一个 view_id。应用数据上报到观测云后,可以先用 Core Web Vitals 判断整体体验,再通过页面、版本、浏览器、设备和网络等维度定位受影响范围,最后沿 view_id 下钻错误、资源、长任务和会话重放。

本文所有字段名均来自 Web RUM SDK 当前上报的数据结构。完整字段清单参见 Web 应用数据采集

分析前先明确统计口径

区分首次加载和路由切换

view_loading_type 用来区分两类 View:

  • initial_load:浏览器首次打开或刷新页面;
  • route_change:单页应用(SPA)发生路由切换。

当前 SDK 只在 initial_load View 上采集 first_bytefirst_contentful_paintlargest_contentful_paintfirst_input_delay 和导航时序字段。loading_timeinteraction_to_next_paintcumulative_layout_shift 及 View 关联计数同时适用于 initial_loadroute_change

因此:

  • 分析首屏、白屏候选、FCP、LCP、TTFB 时,必须筛选 view_loading_type = "initial_load"
  • 分析 SPA 路由性能时,优先使用 loading_timeinteraction_to_next_paintcumulative_layout_shift、错误和长任务等字段;
  • 不要把 route_change 中缺少 FCP 或 LCP 的记录判定为异常。

使用 P75,而不是只看平均值

Core Web Vitals 建议使用页面访问样本的第 75 百分位数(P75)进行评估,并分别观察移动端和桌面端。P75 达标表示至少 75% 的页面访问处于目标范围。平均值容易被大量快速样本稀释,不能代表慢用户的真实体验。

建议同时观察:

  • P50:典型用户体验;
  • P75:Core Web Vitals 主判断口径;
  • P90 或 P95:慢网络、低性能设备等尾部用户体验;
  • 达标率:处于“良好”阈值内的 View 数占有效样本数的比例;
  • 样本量:避免依据少量样本判断页面或版本质量。

指标定义、阈值和 P75 统计方式参考 web.dev:Web Vitals真实环境 Web Vitals 统计最佳实践

注意单位

  • cumulative_layout_shift 外,本文列出的时间指标在数据中均以纳秒(ns)存储;
  • 1s = 1,000,000,000ns1ms = 1,000,000ns
  • cumulative_layout_shift 是无单位分数,不要做时间换算;
  • DQL 阈值必须使用原始存储单位。例如 LCP 2.5 秒应写成 2500000000

核心体验指标

Core Web Vitals

体验维度 SDK 字段 有效 View 良好 需要改进 较差 定位字段
加载性能(LCP) largest_contentful_paint initial_load ≤ 2.5s > 2.5s 且 ≤ 4s > 4s largest_contentful_paint_element_selector
交互响应(INP) interaction_to_next_paint initial_loadroute_change ≤ 200ms > 200ms 且 ≤ 500ms > 500ms interaction_to_next_paint_target_selector
视觉稳定(CLS) cumulative_layout_shift initial_loadroute_change ≤ 0.1 > 0.1 且 ≤ 0.25 > 0.25 cumulative_layout_shift_target_selector

LCP、INP、CLS 的阈值分别参考 LCPINPCLS

LCP:用户何时看到主要内容

largest_contentful_paint 表示视口内最大图片、文本块或视频完成绘制的时间。SDK 同时上报 largest_contentful_paint_element_selector,用于定位产生 LCP 的页面元素。

LCP 较差时,结合以下字段判断时间消耗发生在哪一段:

  1. first_byte 较高:优先检查服务端响应、重定向、CDN、地域和网络;
  2. first_byte 正常但 first_contentful_paint 较高:优先检查阻塞渲染的 CSS、JavaScript 和客户端初始化;
  3. first_contentful_paint 正常但 largest_contentful_paint 较高:优先检查 LCP 元素对应资源是否发现过晚、下载过慢或渲染延迟;
  4. loading_time 仍明显高于 LCP:页面主要内容已可见,但仍有网络请求或 DOM 变动持续发生。

INP:页面是否能及时响应操作

interaction_to_next_paint 衡量一次交互从输入、事件处理到下一帧绘制的完整延迟。SDK 在一个 View 内持续观察交互并报告接近最差交互的值,同时通过 interaction_to_next_paint_target_selector 标识对应元素。

INP 较差时,重点关联:

  • view_long_task_count:页面是否存在阻塞主线程超过 50ms 的任务;
  • view_error_count:交互期间是否发生脚本错误;
  • frustration_count:是否出现重复点击、无效点击或错误点击等挫败行为;
  • R::long_task 中的 durationblocking_durationscripts:定位阻塞时间和相关脚本。

没有用户交互的 View 可能没有 interaction_to_next_paint,统计 INP 时只使用该字段存在的样本。

CLS:页面内容是否意外移动

cumulative_layout_shift 衡量页面可见元素的意外位移,cumulative_layout_shift_target_selector 指向造成最大影响的元素。

CLS 较差时,常见检查方向包括:

  • 图片、视频、广告或 iframe 未预留宽高;
  • 异步内容插入到已有内容上方;
  • Web 字体切换导致文本尺寸变化;
  • 动画通过会触发布局的属性实现。

首次加载辅助指标

SDK 字段 含义 建议用途
first_byte 从导航开始到收到文档响应首字节 判断服务端、网络、重定向或 CDN 是否拖慢后续渲染
first_contentful_paint 首个文本、图片、SVG 或非白色 Canvas 绘制时间 衡量用户何时第一次看到内容,也是白屏候选分析的主要字段
dom_interactive 文档解析器完成解析的时间点 判断 HTML 和同步脚本是否延迟 DOM 可交互状态
dom_content_loaded DOMContentLoaded 完成时间点 判断 DOM 构建和延迟脚本完成时间
dom_complete 页面和子资源完成后的时间点 判断完整文档生命周期是否过长
load_event load 事件完成时间点 判断依赖资源全部加载完成的时间
first_paint_time 当前 SDK 计算的 responseEnd - fetchStart 观察文档响应阶段耗时;不要把它等同于 FCP
time_to_interactive 当前 SDK 计算的 domInteractive - fetchStart 观察 DOM 到达可交互状态的时间;不要与实验室工具的 TTI 混用
dom_ready 当前 SDK 计算的 domContentLoadedEventEnd - fetchStart 观察 DOM Ready 完成耗时
resource_load_time 当前 SDK 计算的 loadEventStart - domContentLoadedEventEnd 观察 DOM Ready 之后等待依赖资源的耗时
dom 当前 SDK 计算的 domComplete - domInteractive 观察 DOM 可交互之后到完整完成的耗时

FCP 可参考 web.dev:FCP:良好为不超过 1.8 秒,较差为超过 3 秒。first_byte 可参考 web.dev:首字节时间:0.8 秒以内通常较好,超过 1.8 秒通常较差;TTFB 不是 Core Web Vitals,应结合 FCP 和 LCP 判断。

页面加载与使用体验指标

SDK 字段 含义 适合回答的问题
loading_time SDK 综合 load 事件、网络请求和 DOM 活动得到的页面稳定耗时 页面何时结束主要加载活动;SPA 路由切换是否持续请求或更新 DOM
time_spent 用户在当前 View 的停留时间 慢页面是否导致快速离开;异常是否影响长时间使用
view_error_count 当前 View 关联的错误数 页面是否因脚本异常不可用
view_resource_count 当前 View 关联的资源请求数 页面是否请求过多;是否需要继续分析资源瀑布
view_long_task_count 当前 View 关联的长任务数 主线程是否频繁被阻塞
view_action_count 当前 View 关联的用户操作数 页面是否真正被使用;INP 样本缺失是否因为没有交互
frustration_count 当前 View 关联的挫败行为数量 用户是否因无响应、无结果或错误而重复操作
is_active View 是否仍处于活跃状态 过滤尚未结束、指标仍可能继续更新的 View
session_has_replay 当前会话是否有关联会话重放 是否可以直接回放异常用户现场

loading_time 不等同于视觉完成时间。页面可以先完成 LCP,但后台轮询、接口请求或持续 DOM 更新会让 loading_time 更长;反之,loading_time 正常也不能证明页面主要内容已经正确显示。

建立页面性能基线

第一步:看每个页面的 P75

下面的查询面向仪表板图表,故意不在 DQL 中写 [24h][1h] 等固定时间范围。省略时间范围后,查询会跟随仪表板右上方的时间控件;如果在 DQL 中直接指定时间范围,其优先级高于仪表板时间控件,会使图表固定查询该时间段。更多说明参见 DQL 时间范围指定。将 <APP_ID> 替换为应用 ID 即可。

按页面查看 LCP P75:

R::view:(percentile(largest_contentful_paint, 75) AS p75_lcp) {app_id = "<APP_ID>", view_loading_type = "initial_load", largest_contentful_paint = exists()} BY view_path_group SORDER BY p75_lcp DESC SLIMIT 20

按页面查看 INP P75:

R::view:(percentile(interaction_to_next_paint, 75) AS p75_inp) {app_id = "<APP_ID>", interaction_to_next_paint = exists()} BY view_path_group SORDER BY p75_inp DESC SLIMIT 20

按页面查看 CLS P75:

R::view:(percentile(cumulative_layout_shift, 75) AS p75_cls) {app_id = "<APP_ID>", cumulative_layout_shift = exists()} BY view_path_group SORDER BY p75_cls DESC SLIMIT 20

不要直接把三个指标相加形成一个分数。LCP、INP、CLS 分别代表加载、响应和稳定性,任一项较差都需要单独定位。

第二步:观察达标率

下面的查询计算 LCP 不超过 2.5 秒的有效 View 占比:

eval(100 * A / B, alias='LCP_good_rate', A="R::view:(count(view_id)) {app_id = '<APP_ID>', view_loading_type = 'initial_load', largest_contentful_paint <= 2500000000}", B="R::view:(count(view_id)) {app_id = '<APP_ID>', view_loading_type = 'initial_load', largest_contentful_paint = exists()}")

同理可将条件替换为:

  • INP 达标:interaction_to_next_paint <= 200000000
  • CLS 达标:cumulative_layout_shift <= 0.1
  • FCP 达标:first_contentful_paint <= 1800000000

分母必须只统计指标存在的有效样本,否则不支持该指标的浏览器、无交互 View 或过早离开的 View 会扭曲结果。

第三步:按关键维度拆分

建议依次使用以下 SDK 字段分组或筛选:

  1. view_path_group:先找出受影响页面;
  2. version:判断是否为新版本回归;
  3. browserbrowser_version_major:判断浏览器兼容性或能力差异;
  4. devicescreen_size:区分设备性能和布局差异;
  5. network_type:区分 Wi-Fi、蜂窝网络和不可达网络;
  6. envservice:避免混合不同环境或服务的数据。

例如,按版本和页面比较 Core Web Vitals:

R::view:(percentile(largest_contentful_paint, 75) AS p75_lcp, percentile(interaction_to_next_paint, 75) AS p75_inp, percentile(cumulative_layout_shift, 75) AS p75_cls) {app_id = "<APP_ID>"} BY version, view_path_group SORDER BY p75_lcp DESC SLIMIT 50

由于 LCP 仅存在于 initial_load,而 INP 可能因没有交互而缺失,生产看板中更建议为三个指标分别创建图表,再使用相同的页面、版本和设备筛选条件联动分析。

白屏与长时间无内容分析

白屏不是 SDK 的直接指标

当前 SDK 不上报名为 white_screen 的字段。白屏只能通过已采集指标构造候选集合,再结合错误、资源、长任务和会话重放确认。

推荐将候选分为两级:

  1. 慢 FCP 候选:first_contentful_paint > 3000000000。表示用户超过 3 秒才看到首个内容,是相对稳定、可统计的白屏体验近似;
  2. FCP 缺失候选:已结束的首次加载 View 停留超过 3 秒,但 first_contentful_paint 不存在。该规则只能用于排查,不能直接等同于白屏。

FCP 缺失还可能由以下情况造成:

  • 当前浏览器不支持 SDK 使用的 FCP 采集能力;
  • 页面在 FCP 产生前进入后台或被隐藏;
  • 用户提前关闭页面;
  • 数据采样、网络上报或页面生命周期提前结束;
  • 错误地把 route_change 纳入分析。

因此,FCP 缺失规则必须筛选 view_loading_type = "initial_load",并按 browser 验证采集覆盖率。浏览器能力边界参见 Browser Support

统计慢 FCP 候选比例

eval(100 * A / B, alias='white_screen_candidate_rate', A="R::view:(count(view_id)) {app_id = '<APP_ID>', view_loading_type = 'initial_load', first_contentful_paint > 3000000000}", B="R::view:(count(view_id)) {app_id = '<APP_ID>', view_loading_type = 'initial_load', first_contentful_paint = exists()}")

该比例表示“有效 FCP 样本中超过 3 秒才看到内容”的比例,不表示经过视觉确认的真实白屏率。建议再按 view_path_groupversionbrowsernetwork_type 拆分。

找出慢 FCP View

R::view:(view_id, session_id, view_url, first_contentful_paint, first_byte, loading_time, view_error_count, view_resource_count, view_long_task_count, session_has_replay) {app_id = "<APP_ID>", view_loading_type = "initial_load", first_contentful_paint > 3000000000} ORDER BY first_contentful_paint DESC LIMIT 100

结果解释:

  • first_byte 同时很高:优先检查服务端、CDN、网络和重定向;
  • first_byte 正常但 FCP 很高:优先检查阻塞渲染资源、客户端渲染和同步 JavaScript;
  • view_error_count > 0:优先查看错误堆栈,确认初始化是否中断;
  • view_long_task_count > 0:检查主线程是否在首次绘制前被长任务阻塞;
  • session_has_replay = true:使用 session_idview_id 打开会话重放确认用户实际看到的画面。

找出 FCP 缺失候选

R::view:(view_id, session_id, view_url, time_spent, view_error_count, view_resource_count, view_long_task_count, session_has_replay) {app_id = "<APP_ID>", view_loading_type = "initial_load", is_active = false, time_spent > 3000000000, first_contentful_paint != exists()} ORDER BY time_spent DESC LIMIT 100

该结果应先按 browser 排除不支持 FCP 的样本,再结合会话重放和下钻查询确认。不能仅根据 FCP 缺失创建“真实白屏率”告警。

沿 view_id 下钻根因

将候选结果中的 <VIEW_ID> 带入下列查询。

查看脚本和运行时错误:

R::error:(error_type, error_source, error_message, error_stack) {app_id = "<APP_ID>", view_id = "<VIEW_ID>"} ORDER BY time ASC LIMIT 100

查看失败或缓慢资源:

R::resource:(resource_url, resource_type, resource_status, duration, resource_ttfb, resource_trans) {app_id = "<APP_ID>", view_id = "<VIEW_ID>", resource_status >= 400} ORDER BY duration DESC LIMIT 100

如果没有 HTTP 错误,但仍怀疑资源过慢,可以移除 resource_status >= 400,再按 duration 查看最慢资源。resource_ttfb 较高通常指向服务端或网络等待,resource_trans 较高通常指向内容传输时间。

查看长任务:

R::long_task:(duration, blocking_duration, scripts) {app_id = "<APP_ID>", view_id = "<VIEW_ID>"} ORDER BY duration DESC LIMIT 100

duration 表示长任务总时长,blocking_duration 表示其中阻塞用户输入的时间,scripts 可用于定位相关脚本。

常见体验问题的判断路径

现象 先看字段 继续关联 常见方向
页面迟迟没有内容 first_contentful_paintfirst_byte view_error_countview_long_task_count、Resource 服务端慢、渲染阻塞、初始化错误、长任务
主要内容加载慢 largest_contentful_paint largest_contentful_paint_element_selector、Resource LCP 资源发现晚、下载慢、渲染延迟
点击后无响应 interaction_to_next_paint interaction_to_next_paint_target_selector、Long Task、Error 主线程阻塞、事件处理过重、脚本错误
页面内容跳动 cumulative_layout_shift cumulative_layout_shift_target_selector 未预留尺寸、动态插入、字体和动画
页面一直显示加载中 loading_time Resource、DOM 活动、Error 请求未结束、轮询、持续 DOM 更新、异常状态未收敛
用户反复点击或点击无结果 frustration_count Action、INP、Error、会话重放 无视觉反馈、无效点击、错误点击、慢交互
新版本体验下降 version + P75 view_path_groupbrowsernetwork_type 资源体积、代码路径、兼容性或发布回归

看板与告警建议

建议至少建立以下视图:

  1. LCP、INP、CLS 的 P75 趋势和达标率;
  2. FCP、first_byteloading_time 的 P75 趋势;
  3. view_path_group 排序的慢页面 Top 20;
  4. version 对比的发布前后趋势;
  5. browserdevicenetwork_type 和地域拆分的尾部体验;
  6. view_error_countview_long_task_countfrustration_count 与性能指标的关联图;
  7. 慢 FCP 候选比例和可回放样本列表。

告警应优先使用 P75 或达标率,并设置最小样本量和连续触发条件,避免少量异常样本或短时间流量波动造成误报。建议从 Core Web Vitals 的“较差”阈值开始,再根据业务页面的重要程度、历史基线和实际流量调整。

在控制台中完成分析

  • 在「用户访问监测 > 分析看板 > Web 端」查看概览、页面性能、资源和错误分析;
  • 在「用户访问监测 > 查看器」通过 view_idsession_id、页面、版本和浏览器筛选原始 View;
  • 进入单个 View 后,关联查看 Resource、Error、Long Task、Action 和会话重放;
  • 需要自定义统计时,使用本文 DQL 创建仪表板图表或用户访问指标检测。

更多控制台能力参见 分析看板查看器用户访问指标检测

文档评价

文档内容是否对您有帮助? ×