浏览器加载渲染网页过程解析(二)
转自:http://blog.csdn.net/longeremmy/article/details/8030736
浏览器的工作机制,一句话概括起来就是:web浏览器与web服务器之间通过HTTP协议进行通信的过程。所以,C/S之间握手的协议就是HTTP协议。浏览器接收完毕开始渲染之前大致过程如下
:
从浏览器地址栏的请求链接开始,浏览器通过DNS解析查到域名映射的IP地址,成功之后浏览器端向此IP地址取得连接,成功连接之后,浏览器端将请 求头信息 通过HTTP协议向此IP地址所在服务器发起请求,服务器接受到请求之后等待处理,最后向浏览器端发回响应,此时在HTTP协议下,浏览器从服务器接收到 text/html类型的代码,浏览器开始显示此html,并获取其中内嵌资源地址,然后浏览器再发起请求来获取这些资源,并在浏览器的html中显示。
离我们最近并能直接显示一个完整通信过程的工具就是Firebug了,看下图:
其中黄色的tips浮层告诉了我们”colorBox.html”从发起请求到关闭连接整个过程中每个环节的时长(域名解析 -> 建立连接 -> 发起请求 -> 等待响应 -> 接收数据),点击该请求,可以获得HTTP的headers信息,包含响应头信息与请求头信息,如:
//响应头信息 HTTP/1.1 304 Not Modified Date: Wed, 02 Mar 2011 08:20:06 GMT Server: Apache/2.2.4 (Win32) PHP/5.2.1 Connection: Keep-Alive Keep-Alive: timeout=5, max=100 Etag: "1e483-1324-a86f5621"
//请求头信息 GET /Docs/eva/api/colorBox.html HTTP/1.1 Host: ued.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Referer: http://ued.com/Docs/ If-Modified-Since: Thu, 17 Feb 2011 10:14:07 GMT If-None-Match: "1e483-1324-a86f5621" Cache-Control: max-age=0
另外,ajax异步请求同样遵循HTTP协议,原理大同小异。
浏览器加载显示html页面内容的顺序
我们经常看到浏览器在加载某个页面时,部分内容先显示出来,又有些内容后显示。那么浏览器加载显示html究竟是按什么顺序进行的呢?
其实浏览器加载显示html的顺序是按下面的顺序进行的:
1、IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的。
2、在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都已经下载完)。
3、如果遇到语义解释性的标签嵌入文件(js脚本,CSS 下载过程会启用单独连接进行下载,并且在下载后进行解析,解析过程中,停止页面所有往下元素的下载。
5、样式表在下载完成后,将和以前下载的所有样式表一起进行解析,解析完成后,将对此前所有元素(含以前已经渲染的)重新进行渲染。
6、JS、CSS中如有重定义,后定义函数将覆盖前定义函数。
Firefox处理下载和渲染顺序大体相同,只是在细微之处有些差别,例如:iframe的渲染
如果你的网页比较大,希望部分内容先显示出来,粘住浏览者,那么你可以按照上面的规则合理的布局你的网页,达到预期的目的。
JS的加载
不能并行下载和解析(阻塞下载)
当 引用了JS的时候,浏览器发送1个jsrequest就会一直等待该request的返回。因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代 码直接改变了DOM树结构,比如使用 document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现.
为了更清楚的显示页面元素的加载顺序,动手写了一个程序,程序对页面中的每个元素都延迟10秒。
程序的位置在见附件。
首先查看TestHtmlOrder.aspx这个页面,使用HttpWatcher来检测页面元素的加载。
从下面的图中可以看到加载顺序。
IE首先加载了主页面TestHtmlOrder.aspx,
下载了主页面后,页面首先显示的是“红色剑灵”、“蓝色剑灵”几个字,但此时显示的是只是黑色字体,没有样式,因为样式还没有下载下来。
接下来页面中的标签是JS标签,属于嵌入文件,因此IE需要将其下载下来。这有两个文件,虽然IE同时能够和WebServer建立两个链接,但是此时并没有使用两个连接,而是使用一个连接,在下载完成后,接下来才下载另外一个文件。
究其原因,是因为JS包含了语法定义,在第二个文件里面的函数可能用到了第一个文件里面的变量和函数,IE没有办法判断,或者需要很耗时的判断,才 能判断文件下载的先后顺序。而在解释方面,IE对JS文件是下载一个,解释一个(可以执行文件TestJsOrder2.aspx)。如果先下载的是第二 个文件,此时就会发生解释错误。因此需要开发者自己在放置JS文件位置时,按先后顺序放好,IE依次下载进行解释。后面的函数覆盖前面的函数定义
在下载完成后,我们看到helloWorld,helloworld2,开始顺序执行。而此时字体的样式表和图片仍然没有下载下来。
在helloWorld,helloWorld2执行过程时,此时页面停留在函数执行的中断点(alert部分)。此时IE并没有去下载CSS的文件。由此说明JS函数的执行会阻塞IE的下载。
接下来我们看到CSS文件的下载也是使用了一个连接,也是串行下载。其串行下载的原因和JS串行下载原因是一样的。
在两个CSS文件下载过程中,我们看到“红色剑灵”,“蓝色剑灵”依次变为红色和蓝色,两者颜色的转换时间相差在10秒,说明样式文件和JS文件一样是下载完一个解析一个的。
现在转到TestCssOrder.aspx看一下,可以看到 开始时“红色剑灵”,“红色强壮剑灵”,显示为红色,过了10秒“蓝色剑灵”显示为蓝色,再过10秒,“红色强壮剑灵”字体变粗了,同时“红色强壮剑灵 2”开始出现。在刚开始“红色剑灵”,“红色强壮剑灵”显示红色时,第三个样式还没有下载下来,此时IE使用已经下载到样式对上面的元素渲染了一遍,此时 虽然“红色剑灵”,“红色强壮剑灵”样式定义不同,但是显示效果一样。第三个文件下载后,此时IE又重新对“红色强壮剑灵”渲染了一遍,此时其变为加粗, 以上所有的文件加载并且渲染完成后,开始渲染下面的标签“红色强壮剑灵2”
有一点需要证明:在IE使用样式对标签进行渲染时,是不是停止了其他页面元素的下载?原来我想通过加长渲染时间(利用滤镜,将标签元素数目增大)来检测,不过没有验证成功。只是从JS函数的执行推断CSS的渲染也是如此。
接下来看到的是图片文件下载,此时看到的是两个图片同时开始下载,而且是下载完成后,立即在页面上开始显示,直到所有的图片下载完成。
注:一个测试文件在网络传输上所花费时间的办法。
首先需要明白检测中w ait值的意义:wait = 服务器所花时间 + 网络时间
服务器所花时间我们可以用Thread.Sleep(10000);来让其休息10s,
比如这个:
由此大概可以计算出 10.002-10 = 0.002秒,这就是大概在网络上所花的时间。