构建DOM树
什么是Dom
- 从页面的视角来看,DOM 是生成页面的基础数据结构。
- 从 JavaScript 脚本视角来看,DOM 提供给 JavaScript 脚本操作的接口,通过这套接口,JavaScript 可以对 DOM 结构进行访问,从而改变文档的结构、样式和内容。
- 从安全视角来看,DOM 是一道安全防护线,一些不安全的内容在 DOM 解析阶段就被拒之门外了
渲染引擎还有一个安全检查模块叫 XSSAuditor,是用来检测词法安全的。在分词器解析出来 Token 之后,它会检测这些模块是否安全,比如是否引用了外部脚本,是否符合 CSP 规范,是否存在跨站点请求等。如果出现不符合规范的内容,XSSAuditor 会对该脚本或者下载任务进行拦截。详细内容我们会在后面的安全模块介绍,这里就不赘述了
Dom树如何生成
在渲染引擎内部,有一个叫HTML 解析器(HTMLParser)的模块,它的职责就是负责将 HTML 字节流转换为 DOM 结构。
详细流程
- 浏览器判断响应头中的 content-type 字段
- 创建渲染进程,网络进程和渲染进程之间会建立一个共享数据的管道
- 渲染进程有一个HTML解析器,动态接受字节流,并解析成DOM
解析DOM的过程
- 通过分词器将字节流转换成 Token
- HTML 解析器维护了一个 Token 栈结构
解析过程中碰到其它文件怎么办
- 解析到script标签时,渲染引擎判断这是一段脚本,此时 HTML 解析器就会暂停 DOM 的解析
- 优化:当渲染引擎收到字节流之后,会开启一个预解析线程,用来分析 HTML 文件中包含的 JavaScript、CSS 等相关文件,解析到相关文件之后,预解析线程会提前下载这些文件。
- 优化:如果 JavaScript 文件中没有操作 DOM 相关代码,就可以将该 JavaScript 脚本设置为异步加载,通过 async 或 defer 来标记代码
- 在执行 JavaScript 之前,需要先解析 JavaScript 语句之上所有的 CSS 样式。
- JavaScript 引擎在解析 JavaScript 之前,是不知道 JavaScript 是否操纵了 CSSOM 的,所以渲染引擎在遇到 JavaScript 脚本时,不管该脚本是否操纵了 CSSOM,都会执行 CSS 文件下载,解析操作,再执行 JavaScript 脚本。
样式计算
将CSS转换成浏览器能够理解的结构
转换样式表中的属性值,使其标准化
- em
- 颜色值 blue、pink -> rgb
- 百分比
计算出DOM树中每个节点的具体样式
布局阶段
创建布局树
布局计算
分层
- 每个节点都属于一个分层
- 第一点,拥有层叠上下文属性的元素会被提升为单独的一层。
- position、z-index、filter、opacity
- 第二点,需要剪裁(clip)的地方也会被创建为图层。比如文字超出盒子大小
绘制
渲染引擎实现图层的绘制与之类似,会把一个图层的绘制拆分成很多小的绘制指令,然后再把这些指令按照顺序组成一个待绘制列表