一、主要模块
1.HTML解析器
解析HTML文本的解析器,主要作用是将HTML代码解析成DOM树
2.CSS解析器
级联样式表的解析器,主要作用是为DOM中的各个元素对象计算出样式信息,
从而为计算最后网页的布局提供基础设施
3.Javascript引擎
解析执行javascript脚本,使用javascript代码可以修改网页的内容,
也能修改css的信息.即javascript可以通过DOM,CSSDOM接口来修改
网页内容和样式信息,从而改变渲染结果
4.布局
在DOM树创建完成之后,渲染引擎需要将DOM节点和样式信息结合起来,
计算他们的大小以及位置等布局信息,形成一个可以表达所有信息的内部模型
5.绘图
使用图形库将布局计算后的各个网页节点,绘制成图形结果
二、模块间是如何协同工作的:
1.将网页内容交由HTML解析器,HTML解析器解析它之后构建成一颗dom树,这期间要是遇到js代码则
交给js引擎去处理;如果网页中包含css样式,则交给css解析器去处理.
2.在dom树建立的过程中,渲染引擎接收来自CSS解析器的样式信息.构建一个新的内部模型.
该模型由布局模块来构建
3.最后由绘图模块完成该模型到图形的绘制
三、详细过程:
1.转化: 浏览器从磁盘或网络读取 HTML 的原始字节,浏览器会将这段原始文件按照相应编码规范进行解码
(现在一般为 utf-8)。
2.符号化:根据 W3C 标准转化为对应的符号。
3.DOM 构建:HTML 解析器会解析其中的 tag 标签,生成 token ,
遇到 CSS 或 JS 会发送相应请求。HTML 解析是阻塞主线程的,CSS一般也是阻塞主线程的,
也就是说它们在解析过程中是无法做出响应的。而 JS 手动添加 async 后达到异步加载,
根据 token 生成相应 DOM 树。
4.CSSOM 构建,添加 CSS 样式生成 CSSOM 树。
5.渲染树构建,从 DOM 树的根节点开始,遍历每个可见的节点,给每个可见节点找到相应匹配的 CSSOM 规则,
并应用这些规则,连带其内容及计算的样式。
6.样式计算,浏览器会将所有的相对位置转换成绝对位置等一系列的样式计算。
7.布局,浏览器将元素进行定位、布局。
8.绘制,绘制元素样式,颜色、背景、大小、边框等。
9.合成,将各层合成到一起、显示在屏幕上
四、一些问题:
1.网络的模型是同步的。网页作者希望解析器遇到 script标记时立即解析并执行脚本。
文档的解析将停止,直到脚本执行完毕。(此处是内联 script)
2.dom树的构建是远快于渲染树的
3.dom树与渲染树的构建几乎是同时进行的,只是渲染树的构建基于dom树
4.如果脚本是外部的,那么整个dom树构建 js解析执行过程都会停止,直到从网络同步抓取资源完成后再继续。
预解析(js)
WebKit 和 Firefox 都进行了这项优化。在执行js脚本时,其他线程会解析文档的其余部分,
找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载,
从而提高总体速度。请注意,预解析器不会修改 DOM 树,而是将这项工作交由主解析器处理;
预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。
这里还是涉及到os的调度算法,时间片轮转概念
5.样式表
另一方面,样式表有着不同的模型。理论上来说,应用样式表不会更改 DOM 树,
因此似乎没有必要等待样式表并停止文档解析。
但这涉及到一个问题,就是脚本在文档解析阶段会请求样式信息。如果当时还没有加载和解析样式,
脚本就会获得错误的回复,这样显然会产生很多问题。这看上去是一个非典型案例,但事实上非常普遍。
Firefox 在样式表加载和解析的过程中,会禁止所有脚本。而对于 WebKit 而言,
仅当脚本尝试访问的样式属性可能受尚未加载的样式表影响时,它才会禁止该脚本。
五、两个事件:
当 onload 事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了。
当 DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash。