问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

DOM深度对网站性能的影响

创作时间:
作者:
@小白创作中心

DOM深度对网站性能的影响

引用
CSDN
1.
https://blog.csdn.net/lgno2/article/details/140029983

你用 Lighthouse 测量过网站性能吗?你可能见过“避免过多的 DOM 节点”的警告,就像下面这样:

Lighthouse 提醒我们,DOM 节点太多会增加内存使用量,还会导致样式计算很耗时。再加上网站上其他各种操作,这会显著影响用户体验,尤其是那些使用低端设备的用户。

前几天,我在看自己网站的性能报告时,就注意到了这个警告。不过,吸引我注意的不是 DOM 元素的总数,而是它下面一个指标:最大 DOM 深度。

上周我写周报时,花了很多时间研究树形数据结构,所以时间复杂度和树的深度之间的关系我还记得很清楚。看到这个指标,我马上就想:

🤔 DOM 深度会影响渲染性能吗?

我们都知道,DOM 是树状结构,树的深度会影响查找元素的速度。看看下面这两棵 DOM 树:

两棵树的元素数量相同,但深度(或者说高度)不同,一棵是 2,另一棵是 6。树越深,访问其中的元素就需要更多操作。

举个例子,假设我们要从根节点开始访问 元素。在浅树上,只需要两步:找到 的子元素数组,然后访问索引 4 处的子元素:

body.children[4];

但在深树上,需要六步才能找到同一个元素:

body.children[0].children[0].children[0].children[0].children[0];

当我们处理二叉搜索树 (BST) 这类数据结构时,树的高度就很重要。为了保证查找等操作的效率,很多数据结构都实现了自平衡 BST,以便在树增长时保持其高度最小。

回到 DOM,理论上,树越深,速度就越慢。但实际情况如何呢?

我做了个小实验来验证一下。

一个小实验

我创建了两个 HTML 页面,只包含三行文字和 100 个空 div。唯一的区别是,一个页面将所有 div 直接放在文档的 body 中,另一个页面则将 div 嵌套起来。

浅元素树的页面像这样:

<html>
  <body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <!-- 95 divs later... -->
    <div>This is the last of 100 divs.</div>
  </body>
</html>

而深树的页面像这样:

<html>
  <body>
    <div>
      <div>
        <div>
          <div>
            <!-- 95 divs later... -->
            <div>This is the last of 100 divs.</div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

我用 Chrome 浏览器运行了性能测试,结果第一个页面的总加载时间(解析 + 渲染 + 绘制)是 51 毫秒,而第二个页面的加载时间是 53 毫秒。

这结果有点出乎意料,差别竟然这么小!

当然,这个例子不太严谨,因为所有 div 都是空的,浏览器只需要渲染几行文本。但我还是期待看到更大的差异。

幸好,编程的魅力就在于此,我只需改几行代码,就能测试更多 div 的情况。我测试了 200 个、300 个、400 个……一直到 500 个 div 时,性能差异终于明显了。

浅树示例在 56 毫秒内渲染了所有 500 个 div,几乎不受 HTML 数量增加 5 倍的影响。但现在嵌套树需要 102 毫秒,几乎是两倍!

我继续测试,最多测试了 5,000 个 div,结果如下:

DOM 元素
浅树加载时间 (毫秒)
嵌套树加载时间 (毫秒)
100
51
53
200
55
58
300
55
74
400
58
87
500
56
102
600
62
116
700
66
145
800
78
151
900
77
165
1,000
83
189
2,000
101
339
3,000
121
509
4,000
142
667
5,000
166
844

值得注意的是,浅树页面和嵌套树页面的大小相同,都包含相同数量的元素,在浏览器上渲染的结果也完全一样。

唯一的区别就是 DOM 树的深度,从上面的表格中我们可以看到,它确实会影响渲染性能。

你可能会说,5,000 的 DOM 深度太夸张了,现实中根本不会有网站这么糟糕……没错,你说得对!

但 5,000 个元素其实很常见,而且真实的网站中,这些元素不会像浅树示例那样都处于同一深度。即使深度只有 32,解析、渲染和绘制这么多元素仍然需要几百毫秒——这还是在 CSS 和 JS 加载之前。

添加一些 CSS

说到 CSS,大型和深层 DOM 树之所以会出问题,是因为它们会导致耗时的样式重新计算。

如果我们给 5,000 个嵌套 div 的例子添加一些文字,然后添加一条 CSS 规则,就能测试样式重新计算的影响:

div {
  padding-top: 10px;
}

这条规则几乎影响页面上的每个元素,所以浏览器需要很长时间才能计算出每个 div 的更新位置。这种耗时的样式重新计算会阻塞主线程,导致网站无响应。

在这个实验中,我们只测量了页面加载性能,但别忘了用户还会在页面加载完成后与页面交互。

所以,关注 DOM 大小和深度非常重要。它们不仅会影响网站加载速度,还会影响所有运行时的操作,比如用户交互时通过 JavaScript 更新 DOM。

那我们该怎么办呢?

最重要的是,定期检查你的 DOM 大小和深度。 我知道这听起来很平常,但我们平时写代码时,通常只关注一小部分 HTML,很容易忽略这些代码片段加起来会有多大。

可以使用 Lighthouse 或 PageSpeed Insights 等工具来测量 DOM 大小和深度。如果你想快速检查当前页面有多少个元素,可以在浏览器的控制台中运行以下代码:

document.querySelectorAll("*").length;

另一个有用的技巧是 减少 CSS 选择器的范围和复杂性。这可以让浏览器更容易找到你想要定位的元素,从而更快地执行样式重新计算。

2017 年的一项研究统计数据显示了 DOM 大小对转化率的影响。

总结

这个小实验让我明白了两件事。

第一,现代浏览器真的很强大! 它们可以在几毫秒内解析、渲染和绘制一个嵌套了数千层的 DOM 树,这太不可思议了。

当然,现实中很少有网站需要 5,000 层的深度,但看到浏览器已经针对这种情况进行了优化,还是让人觉得很安心。

第二,DOM 大小和深度对网站性能的影响比我想象的要大,尤其是与耗时的样式重新计算结合在一起时。

它们的影响力可能不如耗时的 JavaScript 操作那么大,但它们确实会产生影响(而且会很快累积),所以值得关注。

关于这个主题,还有很多值得学习的资料:

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号