背景
性能是网站和应用的支柱,网站性能高,用户体验会更好,同时,网站速度也是搜索引擎排名的一个因素。因此,好的网站性能直接影响我们的收益指标,因此有必要提高网站的性能,从而从技术角度拿到业务收益。
性能优化的指标
RAIL模型是Google给出的一套以用户为中心的性能模型,它提供了一种考虑性能的结构。 该模型将用户体验分解为关键操作(例如,点击、滚动、加载)并帮助您为每个操作定义性能目标。 RAIL分别代表:
- Response:响应
- Animation:动画
- Idle:空闲
- Load:加载
如下图所示:
响应
在 100 毫秒内完成由用户输入发起的转换,让用户感觉交互是即时的。
- 为了确保在 100 毫秒内产生可见响应,需要在 50 毫秒内处理用户输入事件。这适用于大多数输入,例如点击按钮、切换表单控件或启动动画。但是,这不适用于触摸拖动或滚动。
- 尽管听起来可能有些自相矛盾,但是,即时响应用户输入并非总是正确的做法。您可以利用这 100 毫秒的时间窗口来执行其他需要消耗大量资源的工作,但是,注意不能妨碍用户。如果可能,应在后台工作。
- 对于需要 50 毫秒以上才能完成的操作,请随时提供反馈。
50 毫秒还是 100 毫秒?
目标是在 100 毫秒内响应输入,那么,为什么我们的预算只有 50 毫秒?这是因为除输入处理外,通常还有需要执行其他工作,而且这些工作会占用可接受输入响应的部分可用时间。如果应用程序在空闲时间以推荐的 50 毫秒区块执行工作,这就意味着,如果输入在这些工作区块之一中发生,它最多可能会排队 50 毫秒。考虑到这一点,假设只有剩余的 50 毫秒可用于实际输入处理才是安全地做法。下图展示了这种影响,图中显示了在空闲任务期间收到的输入如何排队,从而减少可用的处理时间:
动画
在 10 毫秒内生成一帧
- 在 10 毫秒或更短的时间内生成动画的每一帧。从技术上来讲,每帧的最大预算为 16 毫秒(1000 毫秒/每秒 60 帧≈16 毫秒),但是,浏览器需要大约 6 毫秒来渲染一帧,因此,准则为每帧 10 毫秒。
- 目标为流畅的视觉效果。用户会注意到帧速率的变化。
空闲
最大限度增加空闲时间以提高页面在 50 毫秒内响应用户输入的几率。
加载
- 根据用户的设备和网络能力优化相关的快速加载性能。目前,对于首次加载,在使用速度较慢 3G 连接的中端移动设备上,理想的目标是在 5 秒或更短的时间内实现可交互。
- 对于后续加载,理想的目标是在 2 秒内加载页面。
通过APIs动态获取指标
如何通过api来获取网页的一些实时的指标数据,对我们做优化非常重要。一般情况,我们通过performance对象来获取常规的性能指标数据。 下面我们只介绍我们最常用的值
- navigationStart: 浏览器处理当前网页的启动时间
- fetchStart:浏览器发起HTTP读取文档的毫秒时间戳
- domainLookupStart: 域名查询开始的时间戳
- domainLookupEnd: 域名查询结束的时间戳
- connectStart: HTTP请求开始向服务器发送的时间戳
- connectEnd: 浏览器与服务器链接建立
- requestStart: 浏览器向服务器发出HTTP请求的时间戳
- responseStart: 浏览器从服务器收到第一个字节的时间戳
- responseEnd: 浏览器从服务器收到最后一个字节的时间戳
- domLoading: 浏览器开始解析网页DOM结构的时间
- domInteractive: 网页DOM树创建完成,开始加载内嵌资源时间
- domContentLoadEventStart: 网页domContentLoadd时间发生时的时间错
- domContentLoadedEventEnd: 网页所有需要执行的脚本执行完成的时间, domReady的时间
- loadEventStart: 当前网页load事件回调函数开始执行的时间戳
- loadEventEnd: 当前网页load事件回调函数执行结束的时间戳
性能数据名称 | 描述 | 计算方法 |
---|---|---|
DNS查询时间耗时 | DNS解析耗时 | domainLookupEnd - domainLookupStart |
请求响应耗时 | 网络请求耗时 | responseStart - requestStart |
DOM解析耗时 | DOM解析耗时 | domInteractive - responseEnd |
资源加载耗时 | 资源加载耗时 | loadEventStart - domContentLoadedEventEend |
DOM_READY耗时 | DOM阶段渲染耗时 | domContentLoadedEventEend - fetchStart |
首次渲染耗时 | 首次渲染时间/白屏时间 | responseEnd - fetchStart |
首次可交互耗时 | 首次可交互耗时 | domInteractive - fetchStart |
首包时间耗时 | 首包时间 | responseStart - domainLookupStart |
页面完全加载耗时 | 页面完全加载时间 | loadEventStart - fetchStart |
TCP链接时间 | TCP链接耗时 | connectEnd - connectStart |
自定义指标采集 我们可以通过自定义一些指标来采集我们想要的数据
const observer = new PerformanceObserver((list) => {
for(const entry of list.getEntries) {
console.log(entry)
}
})
observer.observe({ entryTypes: ['longtask'] })
复制代码
可以通过PerformanceObserver.supportedEntryTypes属性来查看支持哪些属性
性能优化的工具
有一些工具可以帮助您自动执行 RAIL 测量。具体使用哪一种取决于您需要什么类型的信息,以及您喜欢什么类型的工作流程。
Chrome DevTools #
Chrome DevTools 对加载或运行页面时发生的一切活动进行深入分析。请参阅分析运行时性能入门,熟悉性能面板 UI。
以下 DevTools 功能密切相关:
- 限制 CPU 性能来模拟功能较弱的设备。
- 限制网络速度来模拟速度较慢的连接。
- 查看主线程活动,以查看记录时主线程上发生的每个事件。
- 查看表中的主线程活动,以根据活动占用的时间多少来对活动进行排序。
- 分析每秒帧数 (FPS) 以衡量您的动画能否真正流畅地运行。
- 使用性能监视器 (Performance Monitor) 实时监控 CPU 使用率、JS 堆大小、DOM 节点数、每秒布局数等。
- 使用网络部分可视化记录时发生的网络请求。
- 在记录时捕获屏幕截图,以便准确回放加载页面时页面的外观,或触发的动画等。
- 查看交互,以便快速识别用户与其交互后,页面上发生的情况。
- 通过在潜在问题侦听器触发时突出显示页面来实时查找滚动性能问题。
- 实时查看绘制事件,以便识别可能损害动画性能的高资源消耗绘制事件。
Lighthouse #
web.dev/measure 下的 Chrome DevTools 中以 Chrome 扩展和 Node.js 模块的形式提供了 Lighthouse,WebPageTest 中也提供了此工具。只要您提供一个 URL,它就会模拟使用速度较慢的 3G 连接的中端设备在页面上运行一系列审核,然后提供关于加载性能的报告以及如何改进的建议。
以下审核密切相关:
响应
- 最大首次输入延迟时间。根据主线程空闲时间估算应用响应用户输入所需的时间。
- 不使用被动侦听器来提高滚动性能。
- 总阻塞时间。测量阻止页面响应用户输入(例如鼠标点击、屏幕点击或按键)的总时间。
- 交互时间。测量用户何时可以稳定地与所有页面元素进行交互。
加载
- 不要注册控制 page 和 start_url 的服务工作进程。服务工作进程可以缓存用户设备上的公共资源,从而减少通过网络获取资源所需的时间。
- 移动网络上的页面加载速度不够快。
- 消除阻塞渲染的资源。
- 延迟处理屏幕外图像。推迟加载屏幕外的图像,在需要时才加载。
- 适当调整图像大小。不要提供明显大于移动视口中呈现的尺寸的图像。
- 避免链接关键请求。
- 不要为其所有资源使用 HTTP/2 。
- 对图像进行高效编码。
- 启用文本压缩。
- 避免网络负载过大。
- 避免 DOM 大小过大。通过仅传送呈现页面所需的 DOM 节点来减少网络字节数量。
WebPageTest 网页性能测试工具 #
WebPageTest 是一款网页性能测试工具,它使用实际浏览器来访问网页并收集计时指标。在 webpagetest.org/easy 上输入一个 URL,您可以获取在真实的 Moto G4 设备上使用速度较慢的 3G 连接时关于该页面的加载性能报告。您也可以将其配置为包含 Lighthouse 审核。
参考资料
使用 RAIL 模型衡量性能(web.dev/rail/)