用户会注意到网站和应用是否运行不畅,因此优化渲染性能至关重要!
当今网络的用户期望他们访问的页面是交互式的且流畅的,这正是您需要日益关注时间和精力的方面。页面不应只是加载快速,还应在其整个生命周期内对用户输入快速响应。实际上,用户体验的这一方面正是交互到下次绘制 (INP) 指标所衡量的。良好的 INP 意味着页面始终如一且可靠地响应用户的需求。
虽然使页面感觉灵敏的主要组成部分涉及您响应用户交互而执行的 JavaScript 量,但用户所期待的是用户界面的视觉变化。用户界面的视觉变化是多种工作类型的结果,通常统称为渲染,并且这项工作需要尽可能快地发生,以使用户体验感觉快速且可靠。
要编写能够快速响应用户交互的页面,您需要了解浏览器如何处理 HTML、JavaScript 和 CSS,并确保您编写的代码(以及您包含的任何其他第三方代码)尽可能高效地运行。
关于设备刷新率的说明

如今,大多数设备每秒刷新屏幕 60 次。每次刷新都会产生您看到的视觉输出,通常称为帧。在以下视频中,演示了帧的概念
虽然设备的屏幕始终以一致的速率刷新,但在设备上运行的应用程序可能不一定总是能够生成足够的帧来匹配该刷新率。例如,如果有动画或过渡效果正在运行,则浏览器需要匹配设备的刷新率,以便在屏幕每次刷新时生成一个帧。
鉴于典型的显示器每秒刷新 60 次,一些简单的数学计算表明,浏览器有 16.66 毫秒的时间来生成每个帧。但实际上,浏览器为每个帧都有自己的开销,因此您的所有工作都需要在 10 毫秒 内完成。当您未能达到此预算时,帧率会下降,并且页面内容会在屏幕上抖动。这种现象通常称为卡顿。
但是,您的目标会根据您尝试执行的工作类型而变化。满足 10 毫秒的阈值对于动画至关重要,其中屏幕上对象的在两个点之间的一系列帧中进行插值。当涉及到用户界面的离散变化时——也就是说,在没有中间任何运动的情况下从一种状态进行到另一种状态——建议您在感觉用户即时的时限内实现此类变化。在这些情况下,通常引用的数字是 100 毫秒,但 INP 指标的“良好”阈值为 200 毫秒或更低,以便适应各种功能不同的设备。
无论您的目标是什么——是为了避免卡顿而生成动画所需的许多帧,还是仅仅为了尽快生成用户界面的离散视觉变化——了解浏览器的像素管道的工作原理对于您的工作至关重要。
像素管道
作为 Web 开发者,您需要了解并注意五个主要领域。这五个领域是您可以最大程度控制的领域,并且每个领域都代表了从像素到屏幕管道中的关键点

- JavaScript: JavaScript 通常用于处理将导致用户界面视觉变化的工作。例如,这可能是 jQuery 的
animate
函数、对数据集进行排序或向页面添加 DOM 元素。虽然 JavaScript 不是触发视觉变化的绝对必要条件,但 CSS 动画、CSS 过渡效果 和 Web Animations API 能够为页面内容制作动画。 - 样式计算: 这是根据匹配的选择器,确定哪些 CSS 规则应用于哪些 HTML 元素的过程。例如,
.headline
是一个 CSS 选择器的示例,它应用于任何具有class
属性值(其中包含headline
类)的 HTML 元素。从那里,一旦知道规则,就会应用这些规则,并计算每个元素的最终样式。 - 布局: 一旦浏览器知道哪些规则应用于元素,它就可以开始计算页面的几何形状,例如元素占用多少空间以及它们在屏幕上的显示位置。Web 的布局模型意味着一个元素会影响其他元素。例如,
<body>
元素的宽度通常会影响其子元素的尺寸,一直到树的上下,因此对于浏览器而言,该过程可能非常复杂。 - 绘制: 绘制是填充像素的过程。它涉及绘制文本、颜色、图像、边框、阴影以及元素在页面上布局计算完成后的所有视觉方面。绘图通常在多个表面上完成,通常称为图层。
- 合成: 由于页面的各个部分可能绘制在多个图层上,因此需要以正确的顺序将它们应用于屏幕,以便页面按预期渲染。这对于彼此重叠的元素尤其重要,因为错误可能会导致一个元素错误地出现在另一个元素的顶部。
像素管道的每个部分都代表着在动画中引入卡顿或延迟帧绘制的机会,即使对于用户界面的离散视觉变化也是如此。因此,务必确切了解您的代码触发了管道的哪些部分,并调查是否可以将更改限制为仅渲染它们所需的像素管道部分。
您可能听说过与“绘制”结合使用的术语“栅格化”。这是因为绘制实际上是两项任务
- 创建绘制调用列表。
- 填充像素。
后者称为“栅格化”,因此每当您在 DevTools 中看到绘制记录时,都应将其视为包括栅格化。在某些架构中,创建绘制调用列表和栅格化是在不同的线程上完成的,但这不在您作为开发人员的控制范围之内。
您不一定总是在每个帧上都接触到管道的每个部分。实际上,当您使用 JavaScript、CSS 或 Web Animations API 进行视觉更改时,管道通常在给定帧中以三种方式展开。
1. JS / CSS > 样式 > 布局 > 绘制 > 合成

如果您更改了“布局”属性,例如更改元素几何形状(如宽度、高度或其位置)的属性(例如 left
或 top
CSS 属性),则浏览器需要检查所有其他元素并“重排”页面。任何受影响的区域都需要重新绘制,最终绘制的元素将需要合成在一起。
2. JS / CSS > 样式 > 绘制 > 合成

如果您更改了 CSS 中元素的“仅绘制”属性(例如,background-image
、color
或 box-shadow
等属性),则布局步骤不是将视觉更新提交到页面所必需的。通过省略布局步骤(如果可能),您可以避免可能代价高昂的布局工作,否则这些工作可能会在生成下一帧时导致明显的延迟。
3. JS / CSS > 样式 > 合成

如果您更改了既不需要布局也不需要绘制的属性,则浏览器可以直接跳到合成步骤。对于页面生命周期中的高压点(例如动画或滚动),这是像素管道中最便宜且最理想的路径。有趣的事实:Chromium 优化了页面滚动,使其尽可能仅在合成器线程上发生,这意味着即使页面没有响应,您仍然可以滚动页面并查看先前绘制到屏幕上的部分。
Web 性能是一门避免工作,同时尽可能提高任何必要工作效率的艺术。在许多情况下,这关乎与浏览器合作,而不是对抗它。值得注意的是,先前在管道中显示的工作在计算成本方面有所不同;有些任务本质上比其他任务更昂贵!
让我们深入了解管道的不同部分。我们将了解常见问题,以及如何诊断和修复这些问题。
浏览器渲染优化

性能对用户至关重要,为了构建良好的用户体验,Web 开发者需要构建能够对用户交互快速做出反应并平稳渲染的网站。性能专家 Paul Lewis 将在此处帮助您消除卡顿并创建保持每秒 60 帧性能的 Web 应用。您将通过本课程学习到剖析应用并识别次优渲染性能原因所需的工具。您还将探索浏览器的渲染管道,并揭示使构建用户会觉得使用起来愉悦的快速网站变得更容易的模式。