渲染性能
作者:Paul Lewis
现在的网络用户希望他们访问的页面具有交互性并且运行顺畅,这正是您需要投入越来越多时间和精力的地方。页面不仅要快速加载,而且要顺畅地运行;滚动应与手指的滑动一样快,并且动画和交互应如丝绸般顺滑。
要编写高性能的网站和应用,您需要了解浏览器如何处理 HTML、JavaScript 和 CSS,并确保您编写的代码(和您要包括的其他第三方代码)尽可能高效地运行。
60fps 与设备刷新率
目前大多数设备的屏幕刷新率为60 次/秒。因此,如果在页面中有一个动画或渐变效果,或者用户正在滚动页面,那么浏览器渲染动画或页面的每一帧的速率也需要跟设备屏幕的刷新率保持一致。
其中每个帧的预算时间仅比 16 毫秒多一点 (1 秒/ 60 = 16.66 毫秒)。但实际上,浏览器有整理工作要做,因此您的所有工作需要在10 毫秒内完成。如果无法符合此预算,帧率将下降,并且内容会在屏幕上抖动。 此现象通常称为卡顿,会对用户体验产生负面影响。
像素管道
您在工作时需要了解并注意五个主要区域。 这些是您拥有最大控制权的部分,也是像素至屏幕管道中的关键点:
- JavaScript
。一般来说,我们会使用 JavaScript 来实现一些视觉变化的效果。比如用 jQuery 的
animate
函数做一个动画、对一个数据集进行排序或者往页面里添加一些 DOM 元素等。当然,除了 JavaScript,还有其他一些常用方法也可以实现视觉变化效果,比如:CSS Animations、Transitions 和 Web Animation API。 - 样式计算。此过程是根据匹配选择器(例如
.headline
或.nav >.nav__item
)计算出哪些元素应用哪些 CSS 规则的过程。从中知道规则之后,将应用规则并计算每个元素的最终样式。 - 布局。在知道对一个元素应用哪些规则之后,浏览器即可开始计算它要占据的空间大小及其在屏幕的位置。网页的布局模式意味着一个元素可能影响其他元素,例如
<body>
元素的宽度一般会影响其子元素的宽度以及树中各处的节点,因此对于浏览器来说,布局过程是经常发生的。 - 绘制。绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。
- 合成。由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。
管道的每个部分都有机会产生卡顿,因此务必准确了解您的代码触发管道的哪些部分。
有时您可能听到与绘制一起使用的术语“栅格化”。这是因为绘制实际上分为两个任务: 1) 创建绘图调用的列表,以及 2) 填充像素。
后者称为“栅格化”,因此每当您在 DevTools 中看到绘制记录时,就应当将其视为包括栅格化。 (在某些架构下,绘图调用的列表创建以及栅格化是在不同的线程中完成,但是这不是开发者所能控制的。)
不一定每帧都总是会经过管道每个部分的处理。实际上,不管是使用 JavaScript、CSS 还是网络动画,在实现视觉变化时,管道针对指定帧的运行通常有三种方式:
1. JS / CSS > 样式 > 布局 > 绘制 > 合成
如果您修改元素的“layout”属性,也就是改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),那么浏览器将必须检查所有其他元素,然后“自动重排”页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需进行合成。
2. JS / CSS > 样式 > 绘制 > 合成
如果您修改“paint only”属性(例如背景图片、文字颜色或阴影等),即不会影响页面布局的属性,则浏览器会跳过布局,但仍将执行绘制。
3. JS / CSS > 样式 > 合成
如果您更改一个既不要布局也不要绘制的属性,则浏览器将跳到只执行合成。
这个最后的版本开销最小,最适合于应用生命周期中的高压力点,例如动画或滚动。
注:如果想知道更改任何指定 CSS 属性将触发上述三个版本中的哪一个,请查看CSS 触发器。如果要快速了解高性能动画,请阅读更改仅合成器的属性部分。
性能是一种避免执行工作的艺术,并且使您执行的任何操作尽可能高效。 许多情况下,这需要与浏览器配合,而不是跟它对着干。 值得谨记的是,上面列出的各项管道工作在计算开销上有所不同;一些任务比其他任务的开销要大!
接下来,让我们深入了解此管道的各个不同部分。我们会以一些常见问题为例,阐述如何诊断和修正它们。
浏览器渲染优化
想深入了解渲染性能吗?快看看这堂课程吧 它能帮助你了解浏览器是如何把HTML/CSS/JavaScript代码转换成屏幕上你看到的一个个像素的 如何使用DevTools来测量页面性能、以及如何优化你的页面渲染速度。