前端学堂
学有所用

HTML解析过程

欢迎学习前端知识体系课程,本系列属于:前端增长教程

资源请求

浏览器第一步先请求资源,这过程和NavigationTiming中定义的一些关键时间节点类似,但有所区别。这块主要是在performance中ResourceTiming规范定义的内容:

请求到资源之后,浏览器解析流程主要包含以下部分:

  1. 解析HTML,构建DOM树(这里遇到外链,此时会发起请求)
  2. 解析CSS,生成CSS规则树
  3. 合并DOM树和CSS规则,生成render树
  4. 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
  5. 绘制render树(paint),绘制页面像素信息
  6. 浏览器会将各层的信息发送给GPU,GPU将各层合成(composite),显示在屏幕上

精心打造全新课程,欢迎吐槽!反馈宝贵意见!

在线视频课程:网易云课堂课程      思否课堂

构建DOM

浏览器请求一个url地址,然后通常web服务器会返回一个html页面,最先返回的就是html文件。

浏览器的HTML解释器获取到的首先是字节码,然后解析成对应字符序列。然后根据HTML解释器的DSL定义的tokens匹配解析成一个个html node节点,根据HTML语法定义的抽象语法树生成对应的树形结构(这期间html可能不规范,浏览器有很多容错机制来保证语法解析,参考嵌套约束),形成DOM树。

构建CSSOM

浏览器加载CSS是同样的资源请求过程,请求后解析流程和HTML类似,CSS解释器会先从适用于该节点的最通用规则开始(例如,如果该节点是 body 元素的子项,则应用所有 body 样式),然后通过应用更具体的规则(即规则“向下级联”)以递归方式优化计算的样式。

需要注意的是:

  • 每个浏览器都有自己默认的样式表
  • 从右到左(内层到外)解析css
  • 规则路径形成规则片段树,片段树集合形成CSSOM

构建RenderTree

DOM树从根节点开始遍历可见节点,这里之所以强调了“可见”,是因为如果遇到设置了类似display: none;的不可见节点,在render过程中是会被跳过的(但visibility: hidden; opacity: 0这种仍旧占据空间的节点不会被跳过render),保存各个节点的样式信息及其余节点的从属关系。

当浏览器通过网络或者本地文件系统加载一个 HTML 文件,并对它进行解析完毕后,内核就会生成它最重要的数据结构 - DOM 树。DOM 树上每一个节点都对应着网页里面的每一个元素,并且网页也可以通过 JavaScript 操作这棵 DOM 树,动态改变它的结构。但是 DOM 树本身并不能直接用于排版和渲染,内核还会生成另外一棵树 - Render 树,Render 树上的每一个节点 - RenderObject,跟 DOM 树上的节点几乎是一一对应的,当一个可见的 DOM 节点被添加到 DOM 树上时,内核就会为它生成对应的 RenderOject 添加到 Render 树上。

Render 树是浏览器排版引擎的主要作业对象,排版引擎根据 DOM 树和 CSS 样式表的样式定义,按照预定的排版规则确定了 Render 树最后的结构,包括其中每一个 RenderObject 的大小和位置,而一棵经过排版的 Render 树,则是浏览器渲染引擎的主要输入,读者可以认为,Render 树是衔接浏览器排版引擎和渲染引擎之间的桥梁,它是排版引擎的输出,渲染引擎的输入。

layout布局

layout的基本单位是BFC(块格式化上下文,Block Format Context)和IFC(行内格式化上下文,Inline Format Context)

从上到下,从左到右,通过布局将样式信息和属性转换为实际可视窗口的相对大小和位置。在layout的过程中会伴随着回流和重绘:

  • reflow(回流): 根据Render Tree布局(几何属性),意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树;
  • repaint(重绘): 意味着元素发生的改变只影响了节点的一些样式(背景色,边框颜色,文字颜色等),只需要应用新样式绘制这个元素就可以了;
  • reflow回流的成本开销要高于repaint重绘,一个节点的回流往往回导致子节点以及同级节点的回流;

reflow回流

现代浏览器会对回流做优化,它会等到足够数量的变化发生,再做一次批处理回流。

引起回流的原因有以下几种:

  1. 页面第一次渲染(初始化)
  2. DOM树变化(如:增删节点)
  3. Render树变化(如:padding改变)
  4. 浏览器窗口resize
  5. 获取元素的某些属性:
    浏览器为了获得正确的值也会提前触发回流,这样就使得浏览器的优化失效了,这些属性包括offsetLeft、offsetTop、offsetWidth、offsetHeight、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、调用了getComputedStyle()或者IE的currentStyle

repaint重绘

  1. reflow回流必定引起repaint重绘,重绘可以单独触发
  2. 背景色、颜色、字体改变(注意:字体大小发生变化时,会触发回流)
  3. 实际上在render时候发生

优化

避免回流和重绘的方法:

  • 避免逐个修改节点样式,尽量一次性修改
  • 使用DocumentFragment将需要多次修改的DOM元素缓存,最后一次性append到真实DOM中渲染
  • 可以将需要多次修改的DOM元素设置display: none,操作完再显示。(因为隐藏元素不在render树内,因此修改隐藏元素不会触发回流重绘)
  • 避免多次读取某些属性(见上)
  • 将复杂的节点元素脱离文档流,降低回流成本
赞(2) 打赏
一分也是爱,觉得好请我喝杯咖啡吧!前端学堂 » HTML解析过程

一分也是爱,觉得好请我喝杯咖啡吧!

支付宝扫一扫打赏

微信扫一扫打赏