2

考虑以下场景:

<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下载和显示?

作者在这里声称:

浏览器只能在任何特定时间点执行 JavaScript 或呈现 UI……想想当页面下载到浏览器时会发生什么。该页面在下载时已开始呈现,然后遇到一个标签。此时,浏览器将无法继续渲染,因为 JavaScript 可能会影响 UI,因此它会等待。

我不明白这是因为 JavaScript 不能修改它之前的内容吗?
例如,如果cool1.js将里面的内容更改为<h1>“Good day”怎么办?

4

2 回答 2

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 运行后才会运行,而boat.gif 直到cool2.js 运行后才会被放入DOM。
  7. boat.gif可以与其他下载并行下载(这取决于浏览器),但直到运行一段时间后才会显示cool2.js。较旧的浏览器可能在运行之前甚至不会开始下载它cool2.js

因此,就性能优化网站的一般建议而言:

  1. 在页面内容之后加载尽可能多的脚本,或者在它们上使用延迟或异步加载。这将防止您的内容在这些脚本等待加载和运行时被阻塞。
  2. 在整个站点中使用通用脚本文件,以便浏览器可以有效地缓存它们。
  3. 尽可能将多个脚本文件合并为一个更大的最小化脚本文件,因为下载单个脚本文件比下载两个脚本文件更快。

async有关使用ordefer属性加载脚本的许多详细信息,请参见相关问题的答案:加载和执行脚本的顺序

于 2013-04-18T23:15:04.393 回答
1

JFriend00 已经有一个很好的答案,但我留下我的答案来回答你问题的另一部分:'为什么脚本阻塞会成为一个问题?

在下载外部 javascript 之前,页面上的渲染会停止,这可能会因为人们放弃等待而失去您的流量。

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

要点是,您需要考虑何时需要特定脚本并相应地放置/加载/执行它们(并且异步会使这变得更加困难,因为您可能需要将外部文件中的函数推迟到页面呈现之前运行,有关如何处理此问题的示例,请参见此页面)。

于 2013-04-18T23:18:02.850 回答