# 站点体验

首先,从站点体验方面来讲,Web Vitals 定义了 LCP、FID、CLS 指标,成为了业界主流的标准。

  • LCP(加载)

最大内容绘制,是用来测量加载的性能。这个指标上报视口中可见的最大图像或文本块的渲染的时间点,为了提供良好的用户体验,LCP 分数最好保证在 2.5 秒以内。

  • FID(可交互性)

第一次输入延迟,用于测量可交互性。FID 衡量的是从用户第一次与页面交互(例如,当他们点击链接,点击按钮,或使用自定义的 JavaScript 驱动的控件)到浏览器实际能够开始响应该交互的时间,为了提供良好的用户体验,站点应该努力使 FID 保持在 100 毫秒以内。

  • CLS(视觉稳定性)

累计布局位移,用于测量视觉稳定性。CLS 是衡量页面的整个生命周期中,发生的每次布局变化中的最大幅度的布局变化得分的指标。为了提供良好的用户体验,站点应该努力使 CLS 分数达到 0.1 或更低。

# 采集指标

# RUM (Real User Monitoring) 指标

  • 包括 FP, TTI, FCP, FMP, FID, MPFID。

RUM 指标的采集,主要依赖于 Event Timing API 进行测量。

以 FID 指标为例,先创建 PerformanceObserver 对象,监听 first-input 事件监听到 first-input 事件后,利用 Event Timing API,通过事件的开始处理时间,减去事件的发生时间,即为FID。

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    const FID = entry.processingStart - entry.startTime;
    console.log('FID:', FID);
  }

});

// Start observing first-input entries.
observer.observe({
  type: 'first-input',
  buffered: true,
});
1
2
3
4
5
6
7
8
9
10
11
12
13

真实用户性能指标也就是上文有所提及的 RUM 以及平台自己扩展的一些额外的指标,包括以下指标:

  • 首次绘制时间( FP ) :即 First Paint,为首次渲染的时间点。

  • 首次内容绘制时间( FCP ) :即 First Contentful Paint,为首次有内容渲染的时间点。

  • 首次有效绘制时间( FMP ) :用户启动页面加载与页面呈现首屏之间的时间。

  • 首次交互时间( FID ) :即 First Input Delay,记录页面加载阶段,用户首次交互操作的延时时间。FID指标影响用户对页面交互性和响应性的第一印象。

  • 交互中最大延时( MPFID ) :页面加载阶段,用户交互操作可能遇到的最大延时时间。

  • 完全可交互时间(TTI):即 Time to interactive,记录从页面加载开始,到页面处于完全可交互状态所花费的时间。

  • 首次加载跳出率:第一个页面完全加载前用户跳出率。

  • 慢开比:完全加载耗时超过 5s 的 PV 占比。

  • 包括 DNS, TCP, DOM 解析等阶段的指标。

Navigation Timing 指标,可以通过 PerformanceTiming 接口得到它们,以加载时间的计算为例:

function onLoad() {
  var now = new Date().getTime();
  var page_load_time = now - performance.timing.navigationStart;
  console.log("User-perceived page loading time: " + page_load_time);
}
1
2
3
4
5
  • 不重复的耗时时段区分:

    • 重定向耗时: redirectEnd - redirectStart
    • DNS 解析耗时: domainLookupEnd - domainLookupStart
    • TCP 连接耗时: connectEnd - connectStart
    • SSL 安全连接耗时: connectEnd - secureConnectionStart
    • 网络请求耗时 (TTFB): responseStart - requestStart
    • HTML 下载耗时:responseEnd - responseStart
    • DOM 解析耗时: domInteractive - responseEnd
    • 资源加载耗时: loadEventStart - domContentLoadedEventEnd
  • 其他组合分析:

    • 白屏时间: domLoading - fetchStart
    • 粗略首屏时间: loadEventEnd - fetchStart 或者 domInteractive - fetchStart
    • DOM Ready 时间: domContentLoadEventEnd - fetchStart
    • 页面完全加载时间: loadEventStart - fetchStart

# Performance API 能收集的指标

  1. performance.navigation: 页面是加载还是刷新、发生了多少次重定向

  2. performance.timing: 页面加载的各阶段时长

  3. performance.memory 内存使用情况

  • 基于 performance 我们可以测量如下几个方面: mark、measure、navigation、resource、paint、frame。

let p = window.performance.getEntries();

  • 重定向次数:performance.navigation.redirectCount

  • JS 资源数量:p.filter(ele => ele.initiatorType === "script").length

  • CSS 资源数量:p.filter(ele => ele.initiatorType === "css").length

  • AJAX 请求数量:p.filter(ele => ele.initiatorType === "xmlhttprequest").length

  • IMG 资源数量:p.filter(ele => ele.initiatorType === "img").length

  • 总资源数量: window.performance.getEntriesByType("resource").length

  • 不重复的耗时时段区分:

    • 重定向耗时: redirectEnd - redirectStart
    • DNS 解析耗时: domainLookupEnd - domainLookupStart
    • TCP 连接耗时: connectEnd - connectStart
    • SSL 安全连接耗时: connectEnd - secureConnectionStart
    • 网络请求耗时 (TTFB): responseStart - requestStart
    • HTML 下载耗时:responseEnd - responseStart
    • DOM 解析耗时: domInteractive - responseEnd
    • 资源加载耗时: loadEventStart - domContentLoadedEventEnd
  • 其他组合分析:

    • 白屏时间: domLoading - fetchStart
    • 粗略首屏时间: loadEventEnd - fetchStart 或者 domInteractive - fetchStart
    • DOM Ready 时间: domContentLoadEventEnd - fetchStart
    • 页面完全加载时间: loadEventStart - fetchStart
  • JS 总加载耗时:

const p = window.performance.getEntries();
let cssR = p.filter(ele => ele.initiatorType === "script");
Math.max(...cssR.map((ele) => ele.responseEnd)) - Math.min(...cssR.map((ele) => ele.startTime));
1
2
3
  • CSS 总加载耗时:
const p = window.performance.getEntries();
let cssR = p.filter(ele => ele.initiatorType === "css");
Math.max(...cssR.map((ele) => ele.responseEnd)) - Math.min(...cssR.map((ele) => ele.startTime));
1
2
3

# PerformanceObserver 能收集的指标

首次绘制时间( FP ) :即 First Paint,为首次渲染的时间点。

首次内容绘制时间( FCP ) :即 First Contentful Paint,为首次有内容渲染的时间点。

首次有效绘制时间( FMP ) :用户启动页面加载与页面呈现首屏之间的时间。

首次交互时间( FID ) :即 First Input Delay,记录页面加载阶段,用户首次交互操作的延时时间。FID指标影响用户对页面交互性和响应性的第一印象。

交互中最大延时( MPFID ) :页面加载阶段,用户交互操作可能遇到的最大延时时间。

完全可交互时间(TTI):即 Time to interactive,记录从页面加载开始,到页面处于完全可交互状态所花费的时间。

# 参考

最全的前端性能定位总结 (opens new window)

带你入门前端工程-谭志光 (opens new window)

前端监控体系及实现技术详解 (opens new window)

如何进行 web 性能监控 (opens new window)

深入浅出 Performance 工具 & API (opens new window)