呈现页面的过程。通过减少浏览器重排来提高性能

呈现页面是一个复杂的过程。当您更改DOM结构或修改CSS时,浏览器需要相应地作出响应。通过了解这个操作是如何进行的,您可以更改方法来提高性能。在本文中,我们将介绍浏览器如何呈现页面、什么是reflow、paint和composition流程以及如何优化呈现。

渲染过程

当浏览器从服务器接收到初始HTML时,整个过程就开始了。首先,浏览器创建两个树:文档对象模型(DOM)和CSS对象模型(CSSOM)。第一个描述内容,第二个表示样式。

创建文档对象模型

根据HTML浏览器的编码读取原始数据并计算出不同的字符。由于这一点,浏览器可以理解创建不同标记的字符序列,比如divimg标签。在称为词法分析的过程中,令牌接收属性,创建节点——也称为对象。

由于HTML描述了标签之间的关系——例如,<body><html>的子元素——因此上面过程中的对象构成了一个树结构。它被称为文档对象模型(DOM),我们可以与之交互。每当浏览器浏览HTML片段时,它就开始上面描述的过程。您可以在开发工具中查找它。

形成CSS对象模型

我们的CSS代码经历了与HTML类似的处理。浏览器将其转换为结构在称为CSS对象模型(CSSOM)的树中的对象。它需要以强调节点之间关系的方式进行安排。浏览器从最一般的规则(例如,应用于整个主体的样式)开始,到最具体的规则(级联向下)。让我们看看开发人员工具。

必须了解处理HTML和CSS都需要计算能力,因此需要时间。在DOM和CSSOM就绪之后,流程的下一部分就开始了。

将DOM和CSSOM合并到渲染树中

浏览器将DOM和CSSOM合并到一个呈现树中。它包含所有可显示的DOM内容。将它引用为可见节点可能会产生误导,因为render three不包含任何带有display:none的元素。另一方面,它确实包含具有可见性的节点:隐藏节点,因为它们仍然占用屏幕上的一些空间。这是我们在本文中进一步探讨的一个重要差异。渲染三就绪后,浏览器可以进入下一个阶段。

回流重绘和复合阶段

回流,也称为布局阶段,负责计算浏览器视图中的确切位置和大小。当我们操作DOM树或以可能影响布局的方式更改样式时,可能会发生这种情况。受影响元素的子元素也将被重新流,以考虑父元素的新布局。兄弟节点将被重新流,因为它们可能会由于布局更改而被移动。受影响节点的祖先也会受到影响,以对其子节点大小的变化做出反应。这是一项相当昂贵的操作。它可能会导致您的页面显著慢下来,因此,理解如何以一种更少发生的方式编写代码是很重要的。

下一个阶段叫做重绘。这是一个填充像素的过程。每当浏览器需要应用可见更改时,就会发生这种情况。这些属性包括backgroundcolorvisibility。除了DOM或CSSOM中的更改外,还可以通过在画布上绘图之类的操作触发它。就性能而言,它仍然非常昂贵,但没有回流那么贵。

复合阶段是把所有涂过的部件放在一起,这样它们就可以显示在屏幕上。在组合过程中,浏览器以正确的顺序组合所有元素层。

介绍CSS触发器的概念

在这里,我们体验了显示和可见性属性之间的另一个重要区别。更改显示涉及到重新流阶段,更改可见性可能只会导致重新绘制。更改CSS属性的值之后需要浏览器的响应。更改CSS属性所需的计算能力因涉及的阶段而异。这个概念有时被称为CSS触发器。

关注表现

我们可以通过多种方式来处理呈现性能。如果我们想要执行的操作需要涉及到reflow阶段,我们可以通过保持DOM树不那么深来改进它。此外,重新流定位为绝对的或固定的元素可能成本更低,因为它可能不会触发相邻节点的重新流。一个接一个地进行多个更改可能会触发多个回流。最好先将它们应用到一个不显示的元素上,这样就可以同时应用它们。下面是使用React这样的解决方案的原因,使用虚拟DOM可以帮助您提高性能。

避免不必要的阶段
在许多情况下,我们可以通过改变方法来防止呈现过程中的某些阶段。以上方法可以显著提高我们的性能,特别是在动画方面。所涉及的阶段越少,保持稳定的FPS速率的机会就越大。最重要的是要避免激活需要重新流阶段的更改。计算每个动画帧中所有元素的几何位置和大小是非常昂贵的。转换属性(如leftright)可能会影响动画的流畅性。

更好的方法是使用transform属性,该属性不会导致其他元素围绕它流动。正因为如此,我们可以避免回流阶段。要查看示例,请查看由css-tricks创建的这个代码页。这个操作可以使用GPU加速来处理,使其更加流畅。还可以使用will-change提示浏览器要对元素执行的转换类型。另一个动画效果好的特性是浏览器可以高度优化的不透明度。

这是因为转换和不透明度可以由合成线程来处理。它与前一个阶段发生的主线程和JavaScript执行的主线程是分开的。即使浏览器被一些昂贵的任务占用,动画仍然可以由合成线程处理。如果动画触发布局阶段的绘制,则需要主线程才能工作。请随意访问Chromium文档以获得更详细的信息。

总结

在本文中,我们讨论了浏览器呈现我们可以看到并与之交互的内容的方式。由于有了这些知识,我们可以改变我们的方法,通过提高性能和使我们的网站感觉更灵敏,为用户提供更好的体验。通过了解reflow、paint、复合阶段和CSS触发器,我们可以优化代码以实现更快的呈现。通过以上知识的应用,我们的页面加载速度更快,动画更流畅。

原文截图(可右键新窗口查看原文)

李, 国轩