浏览器的渲染过程神秘吗?为什么面试的时候老是拿这些东西来问?相信看完这篇文章,你就能理解所有你想知道的东西,把面试官按在地板摩擦也完全不是问题。
当浏览一个网站的时候,有很多因素会影响用户体验。比如加载资源花费时间过长,首屏显示前等待不需要的文件下载等等,我们必须要明白浏览器的渲染过程。这样我们才能去调优,才能写出高质量的代码。
首先,我们需要知道什么是DOM, 当浏览器发送一个请求去服务器获取HTML文档,服务器会以二进制流的形式返回一个实际上是字符串的文档。 它的响应头会设置Content-Type为text/html; charset=UTF-8
这里的text/html是MIME TYPE,它会告诉浏览器这是一个HTML文档,并且是用UTF-8编码的。使用这些信息,浏览器才可以把二进制数据转化成可读的文本文件。
如果运行顺利的话,浏览器可以开始读取HTML文档,典型的文档看起来是这样子的
在上面的文档中,网页依赖于style.css来提供样式给文档元素,main.js 来执行JS操作。我们的页面看起来是这个样
那问题来了,浏览器是怎么根据这些简单的字符就能渲染出来这么漂亮的页面呢?要搞清楚这个,我们需要先搞清楚这些东西, DOM,CSSOM和渲染树 Rer Tree.
文档对象模型 - Document Object Model (DOM)
当浏览器读取HTML代码时, it会遇到HTML元素html, body, p 等,它就创建JavaScript对象叫一个节点(Node)。 最终, 所有HTML元素都被转化成JavaScript对象。 因为每隔HTML元素都有不同的属性, 所以节点会从不同类的构造函数被创建。比如p节点被从HTMLDivElement创建,并且它是继承自Node类。 像我们之前的HTML文档,我们可以使用一个小试验来证明这些。
浏览器已经内置了这些元素类,像HTMLDivElement, HTMLScriptElement, Node等等。 在浏览器通过HTML文档创建了这些节点后,它们会被组织成树形结构。
文档树Dom Tree
我们之前的文档,建立的树形结构,就像上面这样。这个文档树从最上面的HTML元素,向下边搜索边创建。当HTML元素被找到,一个文档节点就会被创建,直到所有节点被完全创建。(注意:一个DOM节点不一定是被HTML元素创建,注释,属性, 文字,它们也会被创建成节点,这里为了简化,我们就仅仅列出了元素节点)
你可以使用Chrome Dev Tool去看他们详细的信息。
JavaScript其实不理解什么是DOM,它并不是JavaScript规范。DOM是浏览器高级Web API,用来给开发人员操作DOM的接口。
层叠样式表模型 CSS Object Model (CSSOM)
当要给我们的网站漂亮的样式,我们需要它来装饰我们的HTML元素。使用CSS选择器,我们可以给DOM元素设置不同的样式属性,比如color或者font-size之类的。
我们有不同的方式来加载样式表,比如使用外部样式文件,嵌入<style>标签,或者写inline的css,我们还能用JS来动态设置它。
比如我们使用下面的CSS作为示例。
在构造DOM之时,浏览器会从所有可能的地方读取CSS(inline,外部css文件,嵌入tag之类的地方)来构造CSSOM。它也是树形结构,每个节点上的样式都将会被应用到DOM元素上。注意,CSS不会被应用到不会显示到屏幕上的元素(比如<meta>, <title>)
我们知道,大多数浏览器都有自己的默认样式,我们叫它user agent stylesheet 浏览器会根据用户输入的CSS覆盖默认样式,从而生成CSS Node。如果某些属性没有被设置,它会根据W3C标准设置成默认值,或继承自父节点。
参见上图,我们的CSSOM树不包括任何非可见元素,并且一些属性都是继承自上层的值。
渲染树 Reder Tree
渲染树也是树型结构,它会结合DOM和CSSOM而生成。通过渲染树,浏览器才可以计算每个可见的元素布局,然后才能把他们显示出来。这样的话,如果没有渲染树,那页面什么也不会显示,这就是为什么我们需要DOM和CSSOM。
渲染树代表了底层的渲染数据,如果不会显示的元素是不会在渲染树中存在的。比如有些元素设置了display:none, 或者他们的宽高为0px,这些都不会出现在渲染树中。
正如你所看到上图那样,DOM+CSSOM=RerTree,它最终会控制页面的显示。
好了,今天就写这里吧,下一次我们重点讨论一下渲染顺序。
接下来更详细的,更重要的流程请看下面一篇:
Web渲染性能,渲染顺序,看完这个你就全懂了(二)