浏览器呈现网页的顺序是什么?为什么脚本阻止会成为一个问题?

时间:2013-04-18 22:53:46

标签: javascript browser rendering

考虑以下情况:

<h1>Hello!</h1>
<script src="cool1.js"></script>
<script src="cool2.js"></script>
<h2>Goodbye!</h2>
<img src="boat.gif" alt="Big Boat">

下载cool1.js时是否表示Hello!已显示,但Goodbye!下载并执行后才会显示cool1.js
什么时候会cool2.js下载(我知道JavaScript是单线程的,所以它必须等待cool1.js完成执行)?什么时候会boat.gif下载并显示?

Here作者声称:

  

浏览器只能在任何地方执行JavaScript或渲染UI   特定的时间点...想一想页面下载会发生什么   到浏览器。该页面在下载时已开始渲染,   然后遇到一个标签。那时,浏览器可以   不再继续渲染,因为JavaScript可能会影响UI,   等等。

我不明白,因为JavaScript无法修改之前的内容吗? 例如,如果cool1.js<h1>内的内容更改为“美好的一天”,该怎么办?

2 个答案:

答案 0 :(得分:3)

脚本块是一个值得关注的问题,因为它推迟(或延迟)HTML文件中脚本之后物理位置的页面元素的可见性,从而延迟了查看者可以看到这些后面的页面元素并使显示整个页面需要更长的时间页。

在这个块中:

<h1>Hello!</h1>
<script src="cool1.js"></script>
<script src="cool2.js"></script>
<h2>Goodbye!</h2>
<img src="boat.gif" alt="Big Boat">

以下是您可以最终说出的内容:

  1. 是的,浏览器会在下载并运行内联脚本时阻止进一步呈现页面。
  2. <h1>Hello!</h1>将在DOM中,并且在cool1.js脚本运行之前可用。
  3. cool1.js脚本将在cool2.js之前运行,并且两者都将在其余DOM可用之前运行。
  4. 下载和执行这两个脚本文件将延迟位于其后的网页其余部分的可见性。这就是为什么建议在您的内容之后尽可能多地添加javascript或使用某种延迟加载,以便尽可能快地显示您的内容,而无需等待脚本运行。
  5. 在显示页面之前,Javascript无法修改页面中的内容。如果脚本在内容之后,则可以在javascript可以修改之前显示内容。在这种情况下,脚本可以修改内容,但它可能已经在预修改状态下显示。如果脚本在内容之前,则内容尚未在DOM中供脚本修改。在这方面的一个技巧是内容最初被隐藏(通过内联样式或CSS规则),因此javascript可以修改它然后使其可见。
  6. 智能浏览器会根据浏览器中的连接限制同时下载cool1.js,cool2.js(甚至可能是boat.gif)。但是,cool2.js将在cool1.js运行之后才会运行,并且在cool2.js运行之后,boat.gif将不会被放入DOM中。
  7. boat.gif可以与其他下载并行下载(由浏览器决定),但在cool2.js运行一段时间后才会显示。较早的浏览器可能甚至不会在cool2.js运行之后才开始下载。
  8. 因此,就优化网站性能的一般建议而言:

    1. 在页面内容之后加载尽可能多的脚本,或者对它们使用延迟或异步加载。这将阻止您的内容在这些脚本等待加载和运行时阻止。
    2. 在整个网站上使用通用脚本文件,以便浏览器可以有效地缓存它们。
    3. 尽可能将多个脚本文件合并为一个较大的最小化脚本文件,因为下载单个脚本文件而不是两个脚本文件的速度更快。
    4. 有关使用asyncdefer属性加载脚本的大量详细信息,请参阅相关问题的此答案:load and execute order of scripts

答案 1 :(得分:1)

JFriend00已经有了一个很好的答案,但是我要回答你的问题的其他部分:'为什么脚本阻塞会引起关注?'

在外部javascript下载之前,在页面上呈现可能可能会在人们放弃等待时丢失流量。

相反,有时一个好主意是异步加载远程Javascript,以便页面可以继续呈现并在后台下载代码。

重点是,您需要考虑何时需要特定脚本并相应地放置/加载/执行它们(而async可能会使这更加困难,因为您可能需要将外部文件中的函数推迟到页面运行已呈现,请参阅this page以获取如何处理此问题的示例。