考虑以下场景:
<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作者声称:
The browser can only be executing JavaScript or rendering UI at any particular point in time ... think of what happens as a page downloads to the browser. The page has started to render as it was downloaded, and then a tag is encountered. At that point, the browser can no longer continue rendering because the JavaScript may affect the UI, and so it waits.
我不明白这一点是因为 JavaScript 无法修改它之前的内容吗?
例如,如果 cool1.js
会怎样?更改了<h1>
里面的内容说“美好的一天”?
最佳答案
脚本 block 是一个问题,因为它推迟(或延迟)物理上位于 HTML 文件中脚本之后的页面元素的可见性,从而延迟这些后面的页面元素对查看者可见的时间,并导致显示整个页面的时间更长页。
在此 block 中:
<h1>Hello!</h1>
<script src="cool1.js"></script>
<script src="cool2.js"></script>
<h2>Goodbye!</h2>
<img src="boat.gif" alt="Big Boat">
以下是您可以得出的结论:
- 是的,浏览器在下载并运行内联脚本时会阻止页面的进一步呈现。
<h1>Hello!</h1>
将位于 DOM 中并在cool1.js
之前可用脚本运行。cool1.js
脚本将在cool2.js
之前运行并且两者都会在 DOM 的其余部分可用之前运行。- 下载和执行这两个脚本文件将延迟位于它们之后的网页其余部分的可见性。这就是为什么建议在内容之后放置尽可能多的 JavaScript 或使用某种延迟加载,以便可以尽快显示您的内容,而无需等待脚本运行。
- Javascript 无法在页面内容显示之前对其进行修改。如果脚本位于内容之后,则在 javascript 修改它之前内容可能已经显示。在这种情况下,脚本可以修改内容,但它可能已经以修改前的状态显示。如果脚本位于内容之前,则内容尚未在 DOM 中供脚本修改。这方面的一个技巧是最初隐藏内容(通过内联样式或 CSS 规则),以便 javascript 可以对其进行修改,然后使其可见。
- 智能浏览器会根据浏览器的连接限制同时下载cool1.js、cool2.js(甚至可能还有boat.gif)。但是,cool2.js 在cool1.js 运行之后才会运行,并且boat.gif 在cool2.js 运行之前不会被放入DOM 中。
-
boat.gif
可能会与其他下载并行下载(这取决于浏览器),但直到cool2.js
之后的某个时间才会显示。已经跑了。较旧的浏览器可能直到cool2.js
之后才开始下载它。已运行。
因此,就性能优化网站的一般建议而言:
- 在页面内容之后加载尽可能多的脚本,或者对它们使用延迟或异步加载。这将防止您的内容在这些脚本等待加载和运行时被阻塞。
- 在整个网站上使用通用脚本文件,以便浏览器可以有效地缓存它们。
- 尽可能将多个脚本文件合并为一个更大的最小化脚本文件,因为下载单个脚本文件比下载两个脚本文件更快。
有关使用 async
加载脚本的更多详细信息,请参阅相关问题的答案。或defer
属性:load and execute order of scripts .
关于javascript - 浏览器呈现网页的顺序是什么?为什么脚本阻塞会成为问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16094408/