浏览器渲染机制、性能优化

556 阅读5分钟

1. 浏览器的每一帧都需要做什么

image.png

浏览器在一帧内需要做的任务有:

  1. 接受用户的输入事件
  2. 执行事件回调
  3. 开始一帧
  4. 执行rAF回调来绘制动画
  5. 见下方 2. 页面渲染过程
  6. 当一帧内执行完上述任务仍有空余时间时,会执行rIC回调。

rAF 和 rIC

(了解)浏览器的刷新率表示一秒绘制多少帧,浏览器大多在60HZ,一帧时间约为16ms(1000ms / 60hz = 16.6)。

2. 页面渲染过程

  1. 解析HTML文件生成DOM Tree。解析CSS文件生成CSSOM Tree(两者是并行的)。
  2. DOM树和CSSOM树合并生成渲染树Render Tree
  3. 遍历渲染树开始 layout布局,计算每个节点的位置大小信息。
  4. 将渲染树每个节点绘制到屏幕上。

3. 网页的正常加载流程、异步加载方式

浏览器在解析 HTML 文件时,如果遇到<script>标签就会暂停解析,将控制权交给 JS 引擎,等待 JS 文件下载(引用外部脚本时、默认同步加载)并执行完成后才会继续解析 HTML。

<script src="path/to/myModule.js" defer></script> 
<script src="path/to/myModule.js" async></script>

为了防止 JS 阻塞 DOM 的解析而出现页面卡顿问题,可以将<script>放在 HTML 底部,或者添加asyncdefer属性

image.png

defer 和 async 都可以实现异步加载脚本,此时会并行解析 HTML,它们的区别在于脚本下载完成后的执行时机

  • defer:等到 HTML 解析完成后再执行脚本。因此多个defer脚本会顺序执行。
  • async:当脚本下载完成后就会立即执行,执行完成后再去解析 HTML。因此多个async脚本的执行顺序不确定。

注意:浏览器会一边下载 HTML,一边开始解析 HTML,不会等待下载完才执行。

4. CSS 和 JS 的阻塞

  1. CSS 不会阻塞 DOM 的解析,但会阻塞 DOM 的渲染后面js脚本的执行。(从2. 页面渲染过程去理解)
    • 不阻塞dom解析:他们两个的解析是并行的。

    • 阻塞dom的渲染:因为渲染树是依赖于dom树和cssom树的,所以它要等待cssom树构建完成。

    • 阻塞js的执行:因为<script>会触发页面渲染,可能需要css来获取元素的样式等,所以要等待css加载完成。

  2. JS 会阻塞 DOM 的解析和渲染
    • 阻塞dom解析:可以将<script>放在 html 底部,或者添加asyncdefer属性。
    • 阻塞dom渲染:从 JS 线程和 GUI 线程互斥来理解。

5. reflow 回流/重排、repaint 重绘,什么情况下会触发

当元素的尺寸或位置发生变化时需要重新计算布局、绘制渲染UI,这就是回流。

触发回流的操作有:

  • dom 元素的移动、增加、减少。
  • dom 元素的几何属性或某些样式width/height/padding/margin/border改变。
  • 元素中的内容(文本内容/图片)发生变化时。
  • 浏览器窗口大小变化。

当元素的某些样式发生变化但没有影响它的几何属性时,只需要重新绘制渲染 UI 即可、不用计算布局,这就是重绘。例如color、background-color、visibility等。

因此,回流一定重绘,但重绘不一定回流。

6. 性能优化:回流与重绘

  • 使用class 选择器一次性修改样式,而不要用style一项项的修改。通过合并多次修改来减少重排重绘的发生次数。
  • 当隐藏元素时使用opacity:0 优先于 visibility: hidden 优先于 display: none。依次为不触发回流重绘、只触发重绘、触发回流。
  • 避免使用table布局,因为一个改动会导致整个 table 的重新布局。
  • scroll、resize等事件进行防抖节流,因为这两者会导致回流。
  • 动画元素使用absolutefixed定位来使它脱离文档流,这样可以减少对其他元素的影响、只回流重绘该动画。
  • 使用虚拟 DOM 库。

注意:因为回流还需要重新计算 layout,所以回流的损耗高于重绘。

7. 加快首屏速度

首屏时间是指浏览器从响应用户输入到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但当前视窗需要渲染完成。加快首屏渲染速度的方法有:

  • 对文件进行压缩合并,能够减少加载时间和 HTTP 请求个数
  • 静态资源使用 CDN。
  • 使用浏览器缓存来缩短资源加载时间。
  • 图片懒加载
  • script标签中使用deferasync,来避免加载脚本时阻塞 HTML 解析。

(了解)白屏时间是指浏览器从响应用户输入到网页开始显示内容的时间。

8. 性能优化

以上均包括,再加上:

  • 性能优化:重排重绘
  • 当有大量数据需要渲染时,使用虚拟化长列表技术。

  1. 页面很卡时怎么分析? 内存泄漏、页面渲染不及时、页面内存占用过多、垃圾回收机制。

  2. CDN 内容分发网络:是一组分布在不同地理位置的服务器。将源网站的资源分发给距离用户最近的服务器节点,能够提高网站的响应速度、及时地响应用户请求。

  3. 图片懒加载:只有当<img>元素在可视区域中时src 属性才会赋值,否则为空值。

    怎么知道元素是否在可视区域中呢?元素距离视窗顶部的距离 小于 视窗高度时说明元素在可视区域中。

  4. 减少 HTTP 请求个数将多个小文件合并成一个大文件发送。因为完整的 HTTP 请求需要经历 DNS解析、TCP 连接等过程,实际下载时间只占总执行时间的小部分比例,所以合并成一个大文件减少浪费的时间。