大型 DOM 大小对互动性的影响比您想象的要大。本指南将说明原因以及您可以采取的措施。
这是无法避免的:在构建网页时,该网页将具有文档对象模型 (DOM)。DOM 表示网页的 HTML 结构,并允许 JavaScript 和 CSS 访问网页的结构和内容。
不过,问题在于 DOM 的大小会影响浏览器快速高效地呈现网页的能力。一般来说,DOM 越大,初始渲染该网页的成本就越高,并且在网页生命周期内更新其渲染的成本也越高。
在具有非常大的 DOM 的网页中,当修改或更新 DOM 的互动触发昂贵的布局工作时,这会影响网页快速响应的能力,从而导致问题。开销大的布局工作会影响网页的 Interaction to Next Paint (INP);如果您希望网页快速响应用户互动,请务必确保 DOM 大小仅为必需的大小。
网页的 DOM 何时会过大?
根据 Lighthouse,当网页的 DOM 大小超过 1,400 个节点时,就属于过大。当网页的 DOM 超过 800 个节点时,Lighthouse 会开始抛出警告。以以下 HTML 为例:
<ul>
<li>List item one.</li>
<li>List item two.</li>
<li>List item three.</li>
</ul>
在上面的代码中,有四个 DOM 元素:<ul>
元素及其三个 <li>
子元素。您的网页几乎肯定会包含比这更多的节点,因此务必要了解如何控制 DOM 大小,以及在网页的 DOM 尽可能小的情况下,如何通过其他策略来优化渲染工作。
大型 DOM 会如何影响网页性能?
大型 DOM 会通过以下几种方式影响网页性能:
- 在网页的初始渲染期间。当 CSS 应用于网页时,系统会创建一个类似于 DOM 的结构,称为 CSS 对象模型 (CSSOM)。随着 CSS 选择器的特异性增加,CSSOM 会变得更加复杂,并且需要更多时间来运行必要的布局、样式设置、合成和绘制工作,才能将网页绘制到屏幕上。这项额外的工作会增加网页加载初期发生的互动的互动延迟时间。
- 当互动通过插入或删除元素或修改 DOM 内容和样式来修改 DOM 时,渲染该更新所需的工作可能会导致非常昂贵的布局、样式设置、合成和绘制工作。与网页的初始渲染一样,当 HTML 元素因互动而插入到 DOM 中时,CSS 选择器特异性的增加会增加渲染工作量。
- 当 JavaScript 查询 DOM 时,对 DOM 元素的引用会存储在内存中。例如,如果您调用
document.querySelectorAll
来选择网页上的所有<div>
元素,那么如果结果返回大量 DOM 元素,内存开销可能会相当大。

所有这些因素都会影响互动性,但上述列表中的第二项尤为重要。如果互动导致 DOM 发生变化,则可能会触发大量工作,从而导致网页的 INP 较差。
如何衡量 DOM 大小?
您可以通过多种方式测量 DOM 大小。第一种方法使用 Lighthouse。运行审核后,当前网页 DOM 的统计信息将显示在“诊断”标题下的“避免 DOM 规模过大”审核中。在此部分中,您可以查看 DOM 元素的总数、包含最多子元素的 DOM 元素以及最深的 DOM 元素。
一种更简单的方法是使用任何主流浏览器中的开发者工具中的 JavaScript 控制台。如需获取 DOM 中的 HTML 元素总数,您可以在网页加载完毕后在控制台中使用以下代码:
document.querySelectorAll('*').length;
如果您想实时查看 DOM 大小更新,还可以使用性能监控工具。借助此工具,您可以将布局和样式设置操作(以及其他性能方面)与当前的 DOM 大小相关联。

如果 DOM 的大小接近 Lighthouse DOM 大小的警告阈值(或完全超出),下一步是找出如何减小 DOM 的大小,以提高网页对用户互动的响应能力,从而提高网站的 INP。
如何衡量受互动影响的 DOM 元素数量?
如果您在实验室中分析缓慢的互动,并怀疑这可能与网页的 DOM 大小有关,则可以选择分析器中标记为“重新计算样式”的任何活动,并观察底部面板中的上下文数据,以确定有多少 DOM 元素受到影响。

在上面的屏幕截图中,请注意,当选择工作区的样式重新计算时,系统会显示受影响元素的数量。虽然上面的屏幕截图显示了 DOM 大小对包含许多 DOM 元素的网页上的渲染工作的影响,但无论在任何情况下,此诊断信息都非常有用,可用于确定 DOM 的大小是否是限制因素,影响了下一个帧在响应互动时需要多长时间才能绘制。
如何减小 DOM 大小?
除了审核网站的 HTML 是否包含不必要的标记之外,减少 DOM 大小的主要方法是减少 DOM 深度。如果浏览器开发者工具的元素标签页中显示的标记如下所示,则表明您的 DOM 可能不必要地过深:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
如果您看到类似这样的模式,则可能可以通过扁平化 DOM 结构来简化它们。这样做会减少 DOM 元素的数量,并可能让您有机会简化页面样式。
DOM 深度也可能是您使用的框架的症状。特别是,基于组件的框架(例如依赖于 JSX 的框架)要求您将多个组件嵌套在父容器中。
不过,许多框架都允许您使用所谓的 fragment 来避免嵌套组件。提供 fragment 作为功能的基于组件的框架包括(但不限于)以下框架:
通过在所选框架中使用 fragment,您可以减小 DOM 深度。如果您担心扁平化 DOM 结构会对样式设置产生影响,不妨使用更现代(也更快速)的布局模式,例如 flexbox 或 grid。
可考虑的其他策略
即使您尽力扁平化 DOM 树并移除不必要的 HTML 元素以尽可能缩小 DOM,但它仍然可能很大,并且在响应用户互动而发生变化时,会触发大量渲染工作。如果您遇到这种情况,可以考虑采取其他策略来限制渲染工作。
考虑采用加性方法
在网页首次呈现时,用户可能无法立即看到网页的大部分内容。这可能是一个通过在启动时省略 DOM 的这些部分来延迟加载 HTML 的机会,但在用户与需要网页初始隐藏部分的网页部分互动时,再添加这些部分。
此方法在初始加载期间以及之后可能都非常有用。对于初始网页加载,您预先承担的渲染工作较少,这意味着您的初始 HTML 载荷会更轻,并且渲染速度会更快。这样一来,关键时段内的互动就有更多机会运行,而无需与主线程争夺注意力。
如果您网页的许多部分在加载时最初处于隐藏状态,那么这也有助于加快触发重新渲染工作的其他互动。不过,随着其他互动向 DOM 添加更多内容,在整个页面生命周期内,随着 DOM 的增长,渲染工作量也会增加。
随着时间的推移向 DOM 添加内容可能很棘手,并且有其自身的权衡取舍。如果您选择这种方式,则很可能需要发出网络请求来获取数据,以便填充您打算添加到网页中的 HTML,以响应用户互动。虽然正在处理的网络请求不会计入 INP,但会增加感知到的延迟时间。如果可以,请显示加载旋转图标或其他指示符,表明正在提取数据,以便用户了解正在进行的操作。
限制 CSS 选择器复杂度
当浏览器解析 CSS 中的选择器时,必须遍历 DOM 树,才能了解这些选择器如何(以及是否)应用于当前布局。这些选择器的复杂程度越高,浏览器在执行网页的初始渲染时需要完成的工作就越多,并且如果网页因互动而发生变化,浏览器还需要进行更多样式重新计算和布局工作。
使用 content-visibility
属性
CSS 提供 content-visibility
属性,可用于以延迟方式呈现屏幕外的 DOM 元素。当元素接近视口时,系统会根据需要渲染这些元素。content-visibility
的优势不仅在于可大幅减少初始网页渲染时的渲染工作量,还可在用户互动导致网页 DOM 发生变化时跳过对屏幕外元素的渲染工作。
总结
将 DOM 大小缩减到仅包含严格必要的内容,是优化网站 INP 的好方法。这样一来,当 DOM 更新时,浏览器执行布局和渲染工作所需的时间就会减少。即使您无法有效减小 DOM 大小,也可以使用一些技术将渲染工作隔离到 DOM 子树,例如 CSS 包含和 content-visibility
CSS 属性。
无论您采用哪种方式,只要能最大限度地减少渲染工作,并减少网页在响应互动时执行的渲染工作量,用户在与您的网站互动时就会感觉网站的响应速度更快。这意味着您网站的 INP 会更低,从而带来更好的用户体验。