# 渲染优化

# 浏览器解析

  1. 浏览器根据下载的文档转成 一个节点对象,放入一个树形结构里,即 DOM 树

  2. 解释器当遇到外部的 css 样式表,就去把资源下载过来。然后把里面的样式也组成一个树形结构,即 CSSOM

  3. 两棵树合并在一起 即 渲染树,

# 关键渲染路径

  1. 触发(js、css 动画)

  2. 重新对样式进行计算

  3. 布局 (大小、位置信息)

  4. 绘制 (真正的将元素画到浏览器上)

  5. 复合 (浏览器为了提高效率会将元素画在不同的层上,然后复合在一起展示给用户)

# 布局与绘制

  • 渲染树只包含网页需要的节点

  • 布局计算每个节点精确的位置和大小 - 盒模型

  • 位置是像素化每个节点的过程

# 影响回流(布局)的操作

第一次页面加载叫布局,之后页面又发生了变化导致再次布局叫做回流。

  • 添加、删除元素

  • 操作 styles

  • display:none

  • offsetLeft,scrollTop,clientWidth

  • 移动元素位置

  • 修改浏览器大小,字体大小

# 避免布局抖动 layout thrashing

  • 避免回流

  • 读写分离

# fastdom

通过批量执行 DOM 读/写操作消除了布局混乱

fastdom.measure(() => {
  console.log("measure");
});

fastdom.mutate(() => {
  console.log("mutate");
});

fastdom.measure(() => {
  console.log("measure");
});

fastdom.mutate(() => {
  console.log("mutate");
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 怎么运行

FastDom 充当您的应用程序/库与 DOM 之间的监管层。通过批量访问 DOM,我们避免了不必要的文档重排,并极大地提高了布局性能。

每个度量/变异作业都被添加到相应的度量/变异队列。在下一帧开始时,使用清空队列(读取然后写入)window.requestAnimationFrame。

FastDom 旨在在应用程序的所有模块中表现得像个单例。当任何模块需要'fastdom'它们返回相同的实例时,这意味着 FastDom 可以协调应用程序范围内的 DOM 访问。

潜在的第三方库可能依赖于 FastDom,并更好地集成到本身使用它的应用程序中。

# 复合线程做什么

  • 将页面拆分图层进行绘制再进行复合

  • 利用 DevTools 了解网页的图层拆分情况

  • 哪些样式仅影响复合

# 只触发图层复合

  • transform: translate();

  • transform: scale();

  • transform: rotate();

  • opacity:

# 减少重绘(repaint)

尽量使用 transform,opacity

# 拆分图层 will-change

CSS 属性 will-change 为 web 开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。

用好这个属性并不是很容易:

  • 不要将 will-change 应用到太多元素上:浏览器已经尽力尝试去优化一切可以优化的东西了。有一些更强力的优化,如果与 will-change 结合在一起的话,有可能会消耗很多机器资源,如果过度使用的话,可能导致页面响应缓慢或者消耗非常多的资源。

  • 有节制地使用:通常,当元素恢复到初始状态时,浏览器会丢弃掉之前做的优化工作。但是如果直接在样式表中显式声明了 will-change 属性,则表示目标元素可能会经常变化,浏览器会将优化工作保存得比之前更久。所以最佳实践是当元素变化之前和之后通过脚本来切换 will-change 的值。

  • 不要过早应用 will-change 优化:如果你的页面在性能方面没什么问题,则不要添加 will-change 属性来榨取一丁点的速度。 will-change 的设计初衷是作为最后的优化手段,用来尝试解决现有的性能问题。它不应该被用来预防性能问题。过度使用 will-change 会导致大量的内存占用,并会导致更复杂的渲染过程,因为浏览器会试图准备可能存在的变化过程。这会导致更严重的性能问题。

  • 给它足够的工作时间:这个属性是用来让页面开发者告知浏览器哪些属性可能会变化的。然后浏览器可以选择在变化发生前提前去做一些优化工作。所以给浏览器一点时间去真正做这些优化工作是非常重要的。使用时需要尝试去找到一些方法提前一定时间获知元素可能发生的变化,然后为它加上 will-change 属性。