加载和执行一个网页的顺序?

我已经完成了一些基于Web的项目,但是我不太关心普通网页的加载和执行顺序。 但是现在我需要知道细节。 很难从Google或SO那里find答案,所以我提出了这个问题。

示例页面如下所示:

<html> <head> <script src="jquery.js" type="text/javascript"></script> <script src="abc.js" type="text/javascript"> </script> <link rel="stylesheets" type="text/css" href="abc.css"></link> <style>h2{font-wight:bold;}</style> <script> $(document).ready(function(){ $("#img").attr("src", "kkk.png"); }); </script> </head> <body> <img id="img" src="abc.jpg" style="width:400px;height:300px;"/> <script src="kkk.js" type="text/javascript"></script> </body> </html> 

所以这是我的问题:

  1. 这个页面如何加载?
  2. 什么是装载顺序?
  3. JS代码是什么时候执行的? (内联和外联)
  4. 什么时候执行(应用)CSS?
  5. $(document).ready何时执行?
  6. 将abc.jpg下载? 或者只是下载kkk.png?

我有以下的理解:

  1. 浏览器首先加载html(DOM)。
  2. 浏览器开始从上到下,逐行加载外部资源。
  3. 如果满足<script> ,加载将被阻塞,并等待JS文件加载并执行,然后继续。
  4. 其他资源(CSS /图像)并行加载并在需要时执行(如CSS)。

或者是这样的:

浏览器parsinghtml(DOM)并以数组或堆栈式结构获取外部资源。 在加载html之后,浏览器开始并行地加载结构中的外部资源并执行,直到所有的资源被加载。 然后,根据JS,DOM将根据用户的行为而改变。

任何人都可以给出详细的解释,当你有一个HTML页面的响应会发生什么? 这在不同的浏览器中有所不同吗? 有关这个问题的任何参考?

谢谢。

编辑:

我用Firebug做了一个Firefox实验。 它显示为以下图像: 替代文字

根据你的样本,

 <html> <head> <script src="jquery.js" type="text/javascript"></script> <script src="abc.js" type="text/javascript"> </script> <link rel="stylesheets" type="text/css" href="abc.css"></link> <style>h2{font-wight:bold;}</style> <script> $(document).ready(function(){ $("#img").attr("src", "kkk.png"); }); </script> </head> <body> <img id="img" src="abc.jpg" style="width:400px;height:300px;"/> <script src="kkk.js" type="text/javascript"></script> </body> </html> 

大致执行stream程如下:

  1. HTML文档被下载
  2. HTML文件的parsing开始
  3. HTML分析到达<script src="jquery.js" ...
  4. jquery.js被下载和parsing
  5. HTMLparsing到达<script src="abc.js" ...
  6. abc.js被下载,parsing并运行
  7. HTMLparsing达到<link href="abc.css" ...
  8. abc.css被下载和parsing
  9. HTMLparsing到达<style>...</style>
  10. 内部的CSS规则被分析和定义
  11. HTMLparsing到达<script>...</script>
  12. 内部Javascript被parsing并运行
  13. HTMLparsing达到<img src="abc.jpg" ...
  14. abc.jpg被下载并显示
  15. HTML分析到达<script src="kkk.js" ...
  16. kkk.js被下载,parsing并运行
  17. HTML文件parsing结束

请注意,由于浏览器的行为,下载可能是asynchronous和非阻塞的。 例如,在Firefox中,这个设置限制了每个域的同时请求数量。

同样取决于组件是否已经被caching,在不久的将来请求中组件可能不再被请求。 如果组件已被caching,组件将从caching加载,而不是实际的URL。

当parsing结束,文档准备好并加载时, onload事件被触发。 因此,当onload被触发时, $("#img").attr("src","kkk.png"); 运行。 所以:

  1. 文件准备就绪,onload被激活。
  2. JavaScript执行命中$("#img").attr("src", "kkk.png");
  3. kkk.png被下载并加载到#img

$(document).ready()事件实际上是所有页面组件加载并准备就绪时触发的事件。 阅读更多关于它: http : //docs.jquery.com/Tutorials : Introducing_$(document).ready()

编辑 – 这部分详细阐述平行或不平行:

默认情况下,根据我目前的理解,浏览器通常以3种方式运行每个页面:HTMLparsing器,Javascript / DOM和CSS。

HTMLparsing器负责parsing和解释标记语言,因此必须能够调用其他两个组件。

例如,当parsing器遇到这一行时:

 <a href="#" onclick="alert('test');return false;" style="font-weight:bold">a hypertext link</a> 

parsing器将进行3个调用,两个到Javascript和一个到CSS。 首先,parsing器将创build这个元素并将其注册到DOM名称空间中,以及与此元素相关的所有属性。 其次,parsing器将调用将onclick事件绑定到这个特定的元素。 最后,它将调用CSS线程来将CSS样式应用于此特定元素。

执行是自顶而下,单线程。 Javascript可能看起来是multithreading的,但事实是Javascript是单线程的。 这就是为什么当加载外部JavaScript文件时,主HTML页面的parsing被暂停。

但是,CSS文件可以同时下载,因为总是应用CSS规则 – 也就是说元素总是用最新定义的CSS规则重新绘制 – 因此使其不受阻挡。

一个元素在被parsing后才会在DOM中可用。 因此,在使用特定元素时,脚本始终放置在窗口onload事件之后或之内。

这样的脚本会导致错误(在jQuery上):

 <script type="text/javascript">/* <![CDATA[ */ alert($("#mydiv").html()); /* ]]> */</script> <div id="mydiv">Hello World</div> 

因为当parsing脚本时, #mydiv元素仍然没有定义。 相反,这将工作:

 <div id="mydiv">Hello World</div> <script type="text/javascript">/* <![CDATA[ */ alert($("#mydiv").html()); /* ]]> */</script> 

要么

 <script type="text/javascript">/* <![CDATA[ */ $(window).ready(function(){ alert($("#mydiv").html()); }); /* ]]> */</script> <div id="mydiv">Hello World</div> 

1)HTML被下载。

2)HTML被逐步parsing。 当资源请求到达时,浏览器将尝试下载资产。 大多数HTTP服务器和大多数浏览器的默认configuration是并行处理两个请求。 IE可以重新configuration为并行下载无限数量的资产。 在互联网上,Steve Souders能够同时下载100多个请求。 脚本请求在IE中阻止并行资源请求的例外情况。 这就是为什么强烈build议将所有JavaScript放在外部JavaScript文件中,并将请求放在HTML中closuresbody标签之前。

3)一旦HTML被parsing,DOM被渲染。 在几乎所有用户代理中,CSS都呈现为与DOM的呈现并行。 因此,强烈build议将所有CSS代码放入文档的<head> </ head>部分中所要求的尽可能高的外部CSS文件中。 否则,页面呈现出现在DOM中的CSS请求位置,然后从顶部开始渲染。

4)只有在DOM被完全渲染并且页面中的所有资源的请求被parsing或超时JavaScript执行onload事件。 IE7,我不确定IE8,如果没有收到来自资产请求的HTTP响应,不会很快超时。 这意味着由JavaScript以内联方式向页面请求的资源,即JavaScript中写入未包含在函数中的HTML标记可以阻止onload事件执行数小时。 如果页面中存在这样的内联代码,并且由于导致代码崩溃的命名空间冲突而无法执行,则可能触发此问题。

在上述步骤中,CPU占用最多的是parsingDOM / CSS。 如果您希望更快地处理您的页面,请通过消除重复指令并将CSS指令合并到尽可能less的元素引用中来编写高效的CSS。 减lessDOM树中节点的数量也将产生更快的渲染。

请记住,您通过HTML或甚至CSS / JavaScript资源请求的每项资产都需要使用单独的HTTP标头。 这消耗了带宽,并且需要按照请求处理。 如果您希望尽可能快地加载页面,请减lessHTTP请求的数量并减lessHTML的大小。 你不会仅仅通过HTML来平均页面权重180k来做你的用户体验。 许多开发人员订阅了一些谬误,用户在6纳秒内对页面内容的质量做出了决定,然后从服务器上清除DNS查询,并在不满意的情况下烧毁他的电脑,相反,他们提供了最漂亮的页面HTML的250k。 保持您的HTML简短而甜蜜,以便用户可以更快地加载您的网页。 没有什么能够提高用户体验,如快速响应的网页。

在Firefox中打开你的页面,并获得HTTPFox插件。 它会告诉你所有你需要的。

在archivist.incuitofind这个:

http://archivist.incutio.com/viewlist/css-discuss/76444

当你第一次请求一个页面时,浏览器向服务器发送一个GET请求,该请求将HTML返回给浏览器。 然后浏览器开始parsing页面(可能在所有页面都被返回之前)。

当它find一个外部实体(如CSS文件,图像文件,脚本文件,Flash文件或页面外部的其他任何内容(在同一个服务器/域上或不在同一个服务器上)的引用时),它准备该资源的另一个GET请求。

但是HTTP标准规定浏览器不应该向同一个域发出两个以上的并发请求。 因此,它将每个请求都放到一个队列中的特定域中,并且在每个实体被返回时,它将启动队列中的下一个请求。

实体返回所花费的时间取决于其大小,服务器当前正在经历的负载以及运行浏览器的计算机与服务器之间的每台计算机的活动。 这些机器的列表原则上可以不同于每一个请求,一个图像可能从美国传到我在大西洋的英国,而另一个从同一台服务器通过太平洋,亚洲和欧洲出来,这需要更长时间。 所以你可能会得到如下的序列,其中一个页面(以此顺序)引用三个脚本文件和五个图像文件,所有这些大小都不相同:

  1. GET脚本1和脚本2; 排队请求script3和images1-5。
  2. script2到达(它比script1小):GET脚本3,队列图像1-5。
  3. script1到达; GET image1,队列images2-5。
  4. image1到达,GET image2,队列images3-5。
  5. 由于networking问题,script3无法到达 – 再次GET脚本3(自动重试)。
  6. image2到达,脚本3仍然不在这里; GET image3,队列图像4-5。
  7. 图像3到达; GET image4,队列image5,script3仍然在路上。
  8. image4到达,GET image5;
  9. image5到达。
  10. script3到达。

简而言之:任何旧命令,取决于服务器在做什么,互联网的其他部分在做什么,是否有任何错误,必须重新获取。 这可能看起来像是一种奇怪的做事方式,但如果不这样做的话,互联网(不仅仅是WWW)在任何程度上都是可行的。

而且,浏览器的内部队列可能不会按照它们在页面中出现的顺序来获取实体 – 这不需要任何标准。

(哦,不要忘记caching,无论是在浏览器和ISPcaching代理cachingnetworking负载。)

如果你问这是因为你想加快你的网站,请检查雅虎的网页加快您的网站的最佳实践 。 它有很多加速您的网站的最佳做法。

Dynatrace AJAX Edition向您显示页面加载,parsing和执行的确切顺序。

AFAIK,浏览器(至less是Firefox)在parsing它时立即请求每个资源。 如果遇到img标签,只要img标签被parsing,就会请求该图片。 甚至可以在它已经收到HTML文件的整体之前…即使这种情况发生,它仍然可以下载HTML文档。

对于Firefox,根据在about:config中设置的方式,可以使用浏览器队列。 例如,它不会尝试一次从同一台服务器下载多于8个文件…额外的请求将被排队。 我认为每个域名都有限制,每个代理限制以及其他内容,都在Mozilla网站上logging,可以在about:config中设置。 我在某个地方看过IE没有这个限制。

一旦主HTML文档被下载并parsingDOM,jQuery就绪事件就会被触发。 然后,一旦所有链接的资源(CSS,图像等)被下载并parsing,就会触发加载事件。 这在jQuery文档中已经清楚了。

如果你想控制所有加载的顺序,我相信最可靠的方法是通过JavaScript。