网页的加载和执行顺序?

时间:2009-11-25 08:26:32

标签: javascript html css

我已经完成了一些基于Web的项目,但我对普通网页的加载和执行顺序没有太多考虑。但现在我需要了解细节。很难找到Google或SO的答案,所以我创建了这个问题。

示例页面如下:

<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. $(文件).ready什么时候执行?
  6. 请下载abc.jpg吗?或者只是下载kkk.png?
  7. 我有以下理解:

    1. 浏览器首先加载html(DOM)。
    2. 浏览器开始逐行加载外部资源。
    3. 如果满足<script>,则加载将被阻止并等待JS文件加载并执行,然后继续。
    4. 其他资源(CSS /图像)并行加载并在需要时执行(如CSS)。
    5. 或者是这样的:

      浏览器解析html(DOM)并获取数组或类似堆栈结构的外部资源。加载html后,浏览器开始并行加载结构中的外部资源并执行,直到加载所有资源。然后,DOM将根据用户的行为进行更改,具体取决于JS。

      任何人都可以详细解释当您获得HTML页面的响应时会发生什么?这在不同的浏览器中有所不同?关于这个问题的任何参考?

      感谢。

      编辑:

      我在Firefox中使用Firebug进行了一项实验。它显示如下图: alt text

7 个答案:

答案 0 :(得分:266)

根据您的样本,

<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. 下载HTML文档
  2. 解析HTML文档
  3. HTML解析达到<script src="jquery.js" ...
  4. jquery.js已下载并解析
  5. HTML解析到达<script src="abc.js" ...
  6. abc.js已下载,解析并运行
  7. HTML解析到达<link href="abc.css" ...
  8. abc.css已下载并解析
  9. HTML解析到达<style>...</style>
  10. 解析和定义内部CSS规则
  11. HTML解析到达<script>...</script>
  12. 解析并运行内部Javascript
  13. HTML解析达到<img src="abc.jpg" ...
  14. abc.jpg已下载并显示
  15. HTML解析达到<script src="kkk.js" ...
  16. kkk.js已下载,解析并运行
  17. HTML文档的解析结束
  18. 请注意,由于浏览器的行为,下载可能是异步和非阻塞的。例如,在Firefox中,此设置限制了每个域的同时请求数。

    此外,根据组件是否已被缓存,可能不会在近期请求中再次请求该组件。如果组件已被缓存,则将从缓存而不是实际URL加载组件。

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

    1. 文档准备就绪,onload被触发。
    2. Javascript执行点击$("#img").attr("src", "kkk.png");
    3. kkk.png已下载并加载到#img
    4. $(document).ready()事件实际上是所有页面组件都已加载并准备就绪时触发的事件。阅读更多相关信息:http://docs.jquery.com/Tutorials:Introducing_$(document).ready()

      编辑 - 这部分详细阐述了并行或非部分:

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

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

      例如,当解析器出现此行时:

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

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

      执行是自上而下和单线程的。 Javascript可能看起来是多线程的,但事实是Javascript是单线程的。这就是为什么在加载外部javascript文件时,主HTML页面的解析被暂停。

      但是,CSS文件可以同时下载,因为CSS规则总是被应用 - 意思是说元素总是重新绘制最新的CSS规则 - 从而使其解锁。

      元素只有在解析后才能在DOM中使用。因此,在处理特定元素时,脚本始终位于窗口onload事件之后或之内。

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

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

      因为解析脚本时,仍未定义#mydiv元素。相反,这将起作用:

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

      OR

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

答案 1 :(得分:33)

1)下载HTML。

2)逐步解析HTML。当达到资产请求时,浏览器将尝试下载资产。大多数HTTP服务器和大多数浏览器的默认配置是并行处理两个请求。 IE可以重新配置为并行下载无限数量的资产。 Steve Souders已经能够在IE上并行下载超过100个请求。例外情况是脚本请求阻止IE中的并行资产请求。这就是强烈建议将所有JavaScript放在外部JavaScript文件中并将请求放在HTML中的结束正文标记之前的原因。

3)解析HTML后,将呈现DOM。 CSS几乎与所有用户代理中的DOM呈现并行呈现。因此,强烈建议将所有CSS代码放入&lt; head&gt;&lt; / head&gt;中请求尽可能高的外部CSS文件中。文件的一部分。否则,页面将呈现为DOM中CSS请求位置的出现,然后从顶部开始渲染。

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

在上述步骤中,CPU密集程度最高的是解析DOM / CSS。如果您希望更快地处理页面,那么通过消除冗余指令并将CSS指令合并到尽可能少的元素引用中来编写高效的CSS。减少DOM树中的节点数也会产生更快的渲染速度。

请注意,您通过单独的HTTP标头请求从HTML或甚至CSS / JavaScript资产中请求的每个资产。这会消耗带宽并需要按请求处理。如果要尽可能快地加载页面,请减少HTTP请求的数量并减小HTML的大小。通过将页面权重平均为180k,仅使用HTML,您就不会对用户体验任何好处。许多开发人员订阅了一些谬论,即用户在6纳秒内决定页面上的内容质量,然后从他的服务器中清除DNS查询并在不满意的情况下烧毁他的计算机,因此他们提供了最美好的可能页面250k的HTML。保持您的HTML简短和甜蜜,以便用户可以更快地加载您的页面。没有什么能像快速响应的网页那样改善用户体验。

答案 2 :(得分:12)

在Firefox中打开您的页面并获取HTTPFox插件。它会告诉你所需要的一切。

在archivist.incuito上找到了这个:

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

  

当您第一次请求页面时,您的   浏览器发送GET请求   server,将HTML返回给   浏览器。然后浏览器启动   解析页面(可能在此之前   已经退回了。)

     

当找到对的引用时   外部实体,如CSS文件,   图像文件,脚本文件,Flash   文件,或外部的任何其他内容   页面(相同的   服务器/域或不),它准备   进一步提出GET请求   资源。

     

但HTTP标准指定   浏览器不应该做更多   超过两个并发请求   相同的域名。所以它提出了每个请求   到队列中的特定域,和   当每个实体返回时,它就会启动   队列中的下一个   域。

     

实体所需的时间   返回取决于它的大小,   目前正在加载服务器   体验和活动   每台机器之间   机器运行浏览器和   服务器。这些机器的清单   原则上可以是不同的   每一个请求,只要一个   图像可能会从美国传到我身边   在英国大西洋上空的同时   来自同一服务器的另一个出来了   通过太平洋,亚洲和欧洲,   这需要更长的时间所以你可能会得到一个   序列如下,其中a   页面有(按此顺序)引用   三个脚本文件和五个图像   文件,所有不同的大小:

     
      
  1. 获取script1和script2; script3和images1-5的队列请求。
  2.   
  3. script2到达(它比script1小):GET script3,queue   images1-5。
  4.   
  5. script1到了; GET image1,queue images2-5。
  6.   
  7. image1到达,GET image2,队列图像3-5。
  8.   由于网络问题,
  9. script3无法到达 - 再次获取脚本3   (自动重试)。
  10.   
  11. image2到了,script3仍然不在这里;获取image3,队列图像4-5。
  12.   
  13. 图像3到达; GET image4,队列image5,script3仍然在路上。
  14.   
  15. image4到达,GET image5;
  16.   
  17. image5到了。
  18.   
  19. script3到达。
  20.         

    简而言之:任何旧订单,取决于   服务器正在做什么,什么   互联网的其余部分正在做,和   是否有任何错误   并且必须重新获得。这可能   看起来像是一种奇怪的做法   事情,但它会完全按字面意思   互联网是不可能的(不是   只是WWW)可以在任何程度上工作   如果没有这样做,可靠性   方式。

         

    此外,浏览器的内部队列   可能无法获取订单中的实体   它们出现在页面中 - 它不是   任何标准都要求。

         

    (哦,不要忘记缓存,两者都在   浏览器和缓存代理   ISP使用它来减轻负载   网络。)

答案 3 :(得分:6)

如果您因为想要加快网站速度而提出此问题,请查看Best Practices for Speeding Up Your Web Site上的Yahoo页面。它有很多加速您网站的最佳实践。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

AFAIK,浏览器(至少是Firefox)在解析每个资源后立即请求它们。如果它遇到img标记,它将在解析img标记后立即请求该图像。甚至在它收到HTML文档的全部内容之前就已经存在了......那就是在发生这种情况时它仍然可以下载HTML文档。

对于Firefox,有适用的浏览器队列,具体取决于它们在about:config中的设置方式。例如,它不会尝试从同一服务器一次下载超过8个文件...其他请求将排队。我认为每个域限制,每个代理限制,以及其他东西,这些都在Mozilla网站上记录,可以在about:config中设置。我在某处看到IE没有这样的限制。

一旦下载主HTML文档并解析了DOM,就会触发jQuery ready事件。然后,一旦下载并解析了所有链接的资源(CSS,图像等),就会触发load事件。它在jQuery文档中很清楚。

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

答案 6 :(得分:0)

选择的答案看起来不适用于现代浏览器,至少在Firefox 52上。我观察到的是加载资源(如css,javascript)的请求是在HTML解析器到达元素之前发出的,例如

<html>
  <head>
    <!-- prints the date before parsing and blocks HTMP parsering -->
    <script>
      console.log("start: " + (new Date()).toISOString());
      for(var i=0; i<1000000000; i++) {};
    </script>

    <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>

我发现加载css和javascript资源的请求的开始时间没有被阻止。看起来Firefox有一个HTML扫描,并在开始解析HTML之前识别关键资源(不包括img资源)。