如果网站和应用运行不佳,用户会注意到,因此优化渲染性能至关重要!
当今网络用户希望他们访问的网页能够提供互动性和流畅性,因此您需要越来越多地将时间和精力投入到这方面。网页不仅应快速加载,还应在整个生命周期内快速响应用户输入。事实上,Interaction to Next Paint (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>
元素的宽度通常会影响树中上下所有子元素的尺寸,因此对于浏览器来说,该过程可能非常复杂。 - 绘制:绘制是填充像素的过程。它涉及在计算元素在网页上的布局后,绘制元素的文字、颜色、图片、边框、阴影以及基本上所有视觉方面。绘制通常是在多个 Surface(通常称为图层)上进行的。
- 复合:由于页面的各个部分可能会绘制到多个图层上,因此需要按照正确的顺序将它们应用到屏幕上,以便页面按预期呈现。对于相互重叠的元素,这一点尤为重要,因为错误可能会导致一个元素错误地显示在另一个元素之上。
像素流水线中的每个部分都有可能导致动画出现卡顿,或者延迟绘制帧,即使是界面上的离散视觉变化也是如此。因此,请务必准确了解您的代码会触发流水线的哪些部分,并调查您是否可以将更改仅限于像素流水线中渲染它们所需的部分。
您可能听说过“光栅化”一词与“绘制”一词搭配使用。这是因为绘制实际上包含两个任务:
- 创建绘制调用列表。
- 填充像素。
后者称为“光栅化”,因此,每当您在 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 会优化页面滚动,使其尽可能仅在 compositor 线程中发生,这意味着即使页面无响应,您仍然可以滚动页面并查看之前绘制到屏幕上的页面部分。
网站性能是一门艺术,需要在尽可能提高任何必要工作的效率的同时,避免工作。在许多情况下,需要与浏览器协同工作,而不是与之对抗。值得注意的是,流水线中之前显示的工作在计算开销方面有所不同;有些任务本身就比其他任务更耗费资源!
我们来深入了解一下该流水线的不同部分。我们将介绍常见问题以及如何诊断和解决这些问题。
浏览器渲染优化

性能对用户而言至关重要。为了打造良好的用户体验,Web 开发者需要构建能够快速响应用户互动并流畅呈现的网站。性能专家 Paul Lewis 将帮助您消除卡顿,并打造能够保持每秒 60 帧性能的 Web 应用。在本课程结束后,您将掌握分析应用性能所需的工具,并找出导致渲染性能不佳的原因。您还将探索浏览器的渲染流水线,并发现有助于更轻松地构建用户会乐于使用的快速网站的模式。