跳到主要内容

认识

2024年04月22日
柏拉文
越努力,越幸运

一、认识


衡量一个站点性能的好坏,我们通常看两个方面: 首屏性能页面加载以后整个交互的流畅程度。这两个指标的好坏,决定了站点是否可以吸引用户和留住用户。

为了能获得好的用户体验,我们常常需要对站点做性能优化。做性能优化,首先要对站点进行性能分析,寻找到底是哪个阶段性能较差,然后具体问题具体分析,找到对应的解决方案。而谈到性能分析,小编猜大家第一时间想到的是应该是打开浏览器 performancenetworklighthouse 面板,然后对页面加载过程进行分析吧。

诚然这是一个有效的办法,但在实际使用时却存在非常大的局限性。也许,我们自己访问站点的时候性能很好,没有什么问题,但用户在实际访问时,由于设备、网络、使用姿势、使用人数、使用时间段、服务吞吐量等原因,整个体验很可能会没有达到我们的预期。这种情况下进行性能分析就非常麻烦了,首先我们无法感知,其次我们也无法在本地直接复现出用户的使用情形。那怎么办呢?

这个时候,我们可以借助性能监控工具来处理这个问题,如 SentryFundebug (当然,也可以自研)。这类工具,可以在用户访问站点时,将首屏性能、用户交互涉及的一些指标数据通过接口上报给监控平台。监控平台接收到上报数据以后,对数据做汇总、计算,然后以可视化图表的方式展示。通过这些图表,我们就可以进行性能分析,找到影响用户体验的因素,非常方便。

在谈论性能时,重要的是做到精确,并且根据能够进行定量测量的客观标准来论及性能。这些标准就是指标。而前端性能监控,就是要监测页面的性能情况,将各种的性能数据指标量化并收集。

二、加载模型


谈到性能优化, 就必须会提及的加载过程模型图:

Preview

这个加载过程模型,是 web 性能工作组 早在 2012 年就针对页面加载过程制定的,定义了从上一个页面结束,到下一个页面从开始加载到完成加载的整个过程。基于这个模型,我们可以获取到页面加载过程中各个阶段的耗时情况,然后分析出页面加载性能。

三、获取方式


3.1 window.performance.timing

最初,我们可以通过 window.performance.timing 这个接口获取加载过程模型中各个阶段的耗时数据。返回的是一个 UNIX 类型的绝对时间,和用户的系统时间相关,分析的时候需要再次计算。

var timing = window.performance.timing;

// 返回数据格式
{
navigationStart, // 同一个浏览器上下文中,上一个文档结束时的时间戳。如果没有上一个文档,这个值会和 fetchStart 相同。
unloadEventStart, // 上一个文档 unload 事件触发时的时间戳。如果没有上一个文档,为 0。
unloadEventEnd, // 上一个文档 unload 事件结束时的时间戳。如果没有上一个文档,为 0。
redirectStart, // 表示第一个 http 重定向开始时的时间戳。如果没有重定向或者有一个非同源的重定向,为 0。
redirectEnd, // 表示最后一个 http 重定向结束时的时间戳。如果没有重定向或者有一个非同源的重定向,为 0。
fetchStart, // 表示浏览器准备好使用 http 请求来获取文档的时间戳。这个时间点会在检查任何缓存之前。
domainLookupStart, // 域名查询开始的时间戳。如果使用了持久连接或者本地有缓存,这个值会和 fetchStart 相同。
domainLookupEnd, // 域名查询结束的时间戳。如果使用了持久连接或者本地有缓存,这个值会和 fetchStart 相同。
connectStart, // http 请求向服务器发送连接请求时的时间戳。如果使用了持久连接,这个值会和 fetchStart 相同。
connectEnd, // 浏览器和服务器之前建立连接的时间戳,所有握手和认证过程全部结束。如果使用了持久连接,这个值会和 fetchStart 相同。
secureConnectionStart, // 浏览器与服务器开始安全链接的握手时的时间戳。如果当前网页不要求安全连接,返回 0。
requestStart, // 浏览器向服务器发起 http 请求(或者读取本地缓存)时的时间戳,即获取 html 文档。
responseStart, // 浏览器从服务器接收到第一个字节时的时间戳。
responseEnd, // 浏览器从服务器接受到最后一个字节时的时间戳。
domLoading, // dom 结构开始解析的时间戳,document.readyState 的值为 loading。
domInteractive, // dom 结构解析结束,开始加载内嵌资源的时间戳,document.readyState 的状态为 interactive。
domContentLoadedEventStart, // DOMContentLoaded 事件触发时的时间戳,所有需要执行的脚本执行完毕。
domContentLoadedEventEnd, // DOMContentLoaded 事件结束时的时间戳
domComplete, // dom 文档完成解析的时间戳, document.readyState 的值为 complete。
loadEventStart, // load 事件触发的时间。
loadEventEnd // load 时间结束时的时间。
}

3.2 window.performance.getEntriesByType('navigation')

后来,window.performance.timing 被废弃,改用 window.performance.getEntriesByType('navigation')。返回的是一个相对时间,可以直接用来分析,非常方便。

不过,光有这些还不够。上面的这些指标,更多是面向开发人员来说的,如果从用户角度来看,不够形象,并且难以理解。实际上,从用户角度来说,用户更加关心页面何时开始渲染、何时渲染出主要内容、何时可以交互、交互否有延迟、页面视觉是否稳定。

3.3 performanceObserver

针对用户关心的这几个方面,官方也提供了对应的指标和相应的获取方式, 那就是 performanceObserver

参考资料


性能优化