最近遇到了这么一个问题,关于HTML页面的加载渲染的顺序,在chorme浏览器控制台的timeline测试许久,结合网上的资料,终于理出了个头绪。其中有两个博主写的很好,以下段落中也进行了参考和摘抄。
浏览器加载、解析、渲染的过程 - 季诗筱的博客 - 博客频道 - CSDN.NET
http://blog.csdn.net/xiaozhuxmen/article/details/52014901
了解html页面的渲染过程 - yuezk - 博客园
http://www.cnblogs.com/yuezk/archive/2013/01/11/2855698.html
正文
一、相关知识点
当浏览器获得一个html文件时,会“自上而下”加载。
- 浏览器会将HTML解析成一个DOM树,构建过程是深度遍历:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。
浏览器将CSS解析成 CSS Rule Tree 。
根据DOM树和CSSOM(CSS Object Model)来构造 Rendering Tree。
有了 Rendering Tree才会进行Layout(计算出每个节点在屏幕中的位置)和painting,不是仅仅有了dom树就可以显示的。
js脚本,主要是通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree.
二、流程
- 浏览器向服务器发出请求,服务器返回html文件,浏览器开始载入html代码并解析。
- <head>标签内有一个<link>标签引用外部CSS文件,下载CSS文件。但解析器没有阻塞,HTML依然继续解析但是不会显示,因为没有CSS还没到手呢。
- 如果CSS是嵌入式的,没关系,只是不用去下载了。CSS拿到手,为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的 html都解析完成之后再去构建和布局render树。它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。
- 接下来遇到了script标签,如果是外部文件,好了,添加到下载的队列中。由于script是必须立刻执行的,所以下载完之前,解析器也阻塞了。如果是嵌入式的就会立刻执行。
- 接下来在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码。 等下载完图片文件后,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;
- 别忘了,后面也许还会有CSS内联代码和js内联代码。orz,这时候又回重新来过。当然也有轻重之分:如果影响了布局浏览器就需要回去重新渲染,这叫做reflow;如果不影响布局只是改变了某个元素的背景颜色,文字颜色等,将只会引起浏览器的repaint,重画某一部分。
三、分析
- script的js代码都是立刻执行的,如果将script标签放在head中,dom有可能带没解析出来会产生一定的错误。
- 解决办法1:将标签放在body标签里的最后的位置。
- 解决办法2:script有两个属性,defer和async。设置defer="defer",脚本会被延迟到整个页面都解析完毕后(遇到