文档解析
在Chrome开发者工具performence栏中可以看到parsing阶段:
HTML parsing(HTML解析)的任务是根据HTML源文件生成parse tree
可以参照《编译原理》理解。对应到词法分析
、语法分析
。
webkit使用了两种非常有名的解析器生成器:用于创建词法分析器的Flex,以及用于创建解析器的Bison(可用于CSS解析)。Flex 的输入是包含标记的正则表达式定义的文件。Bison 的输入是采用 BNF 格式的语言语法规则。HTML的规则比较松散,不属于上下文无关文法,所以传统的自顶向下和自底向上语法分析都不适用。
HTML DTD
DTD
(Document Type Definition,文档类型定义),源于SGML
,定义了合法的元素、属性和层次结构,可以把合法元素和属性理解为词法层面的,层次结构则限定了语法规则。HTML 4.01 中的 doctype 需要对 DTD 进行引用,因为 HTML 4.01 基于 SGML。而 HTML5 不基于 SGML,因此不需要对 DTD 进行引用,但是需要 doctype 来规范浏览器的行为(让浏览器按照它们应该的方式来运行)。这方面还可以参照XML
,XHTML
进行对比。
有关HTML4的文档类型定义规范:https://www.w3.org/TR/html401/sgml/dtd.html
词法分析
采用状态机机制:
这个步骤和一般的编程语言词法分析过程是相同的。
构造解析树
在词法分析的同时,会进行解析树的构造,词法分析器分析得到一个节点都会交给构造器处理。解析树的构造同样采用状态机的机制,不断的接收新的token流,创建对应的标签元素,加入到解析树,改变状态。
整个过程:
CSS parsing
CSS的文法属于上下文无关文法,可以使用自顶向下或自底向上的语法分析器。Webkit使用Flex和Bison解析生成器从CSS语法文件中自动生成解析器。Chrome 开发者工具performence相应的事件:
最终得到这样一个语法分析树:
整个流程:
渲染树构建
-
从 DOM 树的根节点开始遍历每个可见节点。
-
- 某些节点不可见(例如脚本标记、元标记等),因为它们不会体现在渲染输出中,所以会被忽略。
- 某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略,例如,上例中的 span 节点---不会出现在渲染树中,---因为有一个显式规则在该节点上设置了“display: none”属性。
-
对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。
-
发射可见节点,连同其内容和计算的样式。
Layout和Paint
当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为layout或reflow。所以在元素的大小和位置发生变化时都会触发layout。
浏览器针对Layout做了一定优化,如采用Dirty bit系统,只针对具有dirty标记的元素进行重新layout,即增量layout,且此过程是异步的;如果元素只是位置发生变化,其大小从缓存里读取,就不用再次计算。
绘制阶段,遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础组件。当元素的位置和大小没有变化,如改变背景颜色等等,只会进行重新paint。Paint也采用dirty机制进行增量Paint。
参考资料: