浏览器渲染步骤:
- 解析 HTML 文档,构建 DOM 树
- 解析 CSS 文档,构建 CSSOM 树
- DOM 树 与 CSSOM 树 合并成 Render 树
- 根据 Render 树布局,计算每个节点的布局信息并绘制到屏幕上
如果 DOM 或 CSSOM 被修改,就会重新执行上面所有步骤,即引发回流重绘。
构建对象模型(DOM,CSSOM)
构建 DOM
- 将 HTML 文档根据文件制定编码(charset,例:utf-8)解析成 HTML 字符串。
- 解析 HTML 字符串,将标签转化为节点。
- 根据标签节点构建 DOM。
构建 CSSOM
- 解析 HTML 遇到 link 标签时,会请求资源。
- 解析 CSS 字符串,转换成节点。
- 根据节点构建 CSSOM。
CSSOM 和 DOM 是独立的数据结构。
Render 树合成及绘制
CSSOM 树和 DOM 树合并成 Render 树,计算每个可见元素的布局,并输出给绘制流程,将像素渲染到屏幕上。
合成步骤:
- 从 DOM 树的根节点开始,遍历每个可见节点。
可见节点性:display:none 与 visibility:hidden
对于每个可见节点,为其找到对应的 CSSOM 规则并应用它。
生成 Render 树
绘制:
- 布局阶段:输出盒模型
- 绘制阶段:输出屏幕像素
CSS 阻塞渲染
CSS 不会阻塞 DOM 树解析,但会阻塞 Render 树渲染。
渲染时需等 CSS 加载完毕,因为 Render 树需要从 CSSOM 上查找规则。
所以需要将 CSS 资源尽早、尽快地下载到客户端。
将外部样式的引入放在 head 标签中,在 body 渲染前把 CSSOM 构建好。
JavaScript 阻塞渲染
JavaScript 会阻塞 DOM 解析和 Render 树渲染。
可以让 JavaScript 异步执行,去除关键渲染路径中不必要的 JavaScript。
async 和 defer
- async 属性:[加载和渲染后续文档元素的过程] 和 [JavaScript 的加载与执行] 并行进行(异步)。
脚本之间无顺序。
- defer 属性: [加载后续文档元素的过程] 和 [JavaScript 的加载] 并行进行(异步)。但 [JavaScript 的执行] 要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
脚本之间按顺序。