大型 DOM 树会以多种方式降低网页性能:
网络效率和负载性能
大型 DOM 树通常包含许多用户首次加载页面时不可见的节点,这会不必要地增加用户的数据费用并延长加载时间。
运行时性能
当用户和脚本与您的页面互动时,浏览器必须不断重新计算节点的位置和样式。大型 DOM 树与复杂的样式规则相结合可能会严重降低渲染速度。
内存性能
如果您的 JavaScript 使用常规查询选择器(例如
document.querySelectorAll('li')
),您可能会在无意中存储了对大量节点的引用,这可能会使用户设备的内存容量超负荷。
Lighthouse DOM 大小审核如何失败
Lighthouse 报告页面的 DOM 元素总数、页面的最大 DOM 深度及其子元素数量上限:
![避免进行过多的 DOM 大小 Ligthhouse 审核,其中显示 DOM 元素总数、最大 DOM 深度和最大子元素。](https://developer.chrome.google.cn/static/docs/lighthouse/performance/dom-size/image/lighthouse-excessive-dom-size-audit.png?authuser=9&hl=cs)
Lighthouse 使用符合以下条件的 DOM 树标记网页:
- 当 body 元素所含的节点超过 800 个左右时发出警告。
- 当 body 元素所含的节点数量超过约 1,400 个时出现的错误。
如何优化 DOM 大小
一般来说,应设法仅在需要时创建 DOM 节点,并在不再需要节点时将其销毁。
如果您要交付大型 DOM 树,请尝试加载页面并手动记录显示的节点。或许您可以从最初加载的文档中移除未显示的节点,并仅在相关用户互动(例如滚动或点击按钮)后创建这些节点。
如果您在运行时创建 DOM 节点,子树修改 DOM 更改断点可以帮助您确定节点的创建时间。
如果您无法避免大型 DOM 树,另一种提高渲染性能的方法是简化 CSS 选择器。如需了解详情,请参阅 Google 的缩小样式计算的范围并降低其复杂性。
有关详情,请参阅 DOM 大小对互动性的影响以及可以采取的措施一文。
针对特定堆栈的指南
Angular
如果您要呈现大型列表,请使用 Component Dev Kit (CDK) 中的虚拟滚动功能。
回应
- 如果您要在网页上渲染许多重复元素,请使用
react-window
等“窗口”库来最大限度地减少创建的 DOM 节点数量。 - 使用
shouldComponentUpdate
、PureComponent
或React.memo
最大限度地减少不必要的重新渲染。 - 如果您使用
Effect
钩子提高运行时性能,请仅在某些依赖项发生更改之前跳过效果。