一、html的解析过程
浏览器渲解析和渲染HTML是一个极其复杂的过程,通过一系列的处理将从服务器接收到的HTML字符转换为一个个屏幕上的像素点形成图像。
解析过程如下: 浏览器的网络线程从服务器发起请求并接收到html之后,会在js任务队列中启动一个html解析任务,自此开始html的解析。
一、生成DOM树
浏览器的js主线程会从上到下解析html的内容生成DMO树,解析的过程遇到js会先加载和执行完js然后继续进行解析,CSS样式文件会由预解析线程先行下载和解析,然后js主线程在解析的时候可以直接使用
二、CSSOM树的生成
解析CSS文件生成CSSOM树,根据样式计算(css层叠、属性集成等)得到最终样式。
三、渲染树的生成
遍历DOM树结合CSSOM树得到渲染树。
- 过滤不可见节点:剔除display: none的元素,保留可见节点(如visibility: hidden仍占据空间)。
- 添加伪元素:将::before、::after等伪元素加入渲染树。
四、布局树
遍历渲染树的每个节点,计算得到每个节点的几何信息,如width、marign。
五、分层
将布局树得到的内容进行分层(Layer),进行优化
六、生成绘制指令集
JS主线程根据分层生成绘制指令集
七、分块
将每一层进行分块,得到更小的独立单元
八、光栅化
对每一个块进行处理得到包含像素信息的位图,这个过程会启动GPU进行加速
九、合成
浏览器的合成线程会对光栅化后的位图根据进行合成,得到最终画面的合成帧。
十、显示
浏览器进程启动GPU将合成帧包含的位图绘制到屏幕。
二、回流(reflow)和重绘(repaint)
- 元素的的几何信息(位置、大小等)发生变化的时候会触发回流,会从新生成布局树,布局树之后的解析流程也要再走一遍比较消耗性能。
- 元素的颜色等非几何信息发生变化的时候会触发重绘,除了不需要重新计算布局树,之后的分层等解析步骤也要走一遍。回流一定会触发重绘。
三、提高渲染性能
- 尽量减少页面的回流和重绘
- 重绘的性能优于回流,特殊场景下可以使用重绘代替回流
- 使用el.offsetTop代替el.style.top ,offsetTop是布局属性,布局属性的读取会触发回流
- 多使用transform、opacity,transformg和opacity是在图块合成阶段生效,不消耗性能。
四、总结
- 核心流程:DOM → CSSOM → Render Tree → Layout Tree→ Paint → Composite
- JS的下载和执行、以及css的下载会阻塞html的解析
- 多使用transform/opacity是性能优化的王牌