脚本下载和执行的顺序与 document.write .

Order of script download and execution with document.write

本文关键字:document write 顺序 下载和 执行 脚本      更新时间:2023-09-26

我有这段代码:

<script>
    document.write('<script src="1.js"><'/script>');
</script>
<script>
    document.write('<script src="2.js"><'/script>');
</script>
<script src="3.js"></script>

在网络控制台中,我可以看到3.js是在1.js2.js之前下载的。但是,执行顺序符合预期(1.js2.js3.js)。

据我所知,document.write正在阻塞,因此应在调用document.write后下载脚本3.js

为什么3.js在插入document.write脚本之前下载?

执行顺序是有保证的,因为 HTML 解析器在解析和执行 JavaScript 时会阻塞。如果脚本具有尚未下载的 src URL(见下文),则必须在解析脚本之前执行此操作。这是个坏消息 - 这意味着HTML解析器无法继续读取文档,因为它正在等待可能较慢的HTTP响应。

在您的示例中,HTML 解析器必须等到执行第一个内联<script>后才能移动到下一个输入。

执行后,下一个输入是它插入到文档中的<script src="1.js"... >。HTML 解析器在移动到下一个内联脚本之前被获取、解析和执行时会阻塞,依此类推。这将导致执行顺序:

  1. <script>document.write('<script src="1.js"><'/script>');</script>
  2. <script src="1.js"></script>
  3. <script>document.write('<script src="2.js"><'/script>');</script>
  4. <script src="2.js"></script>
  5. <script src="3.js"></script>

但是,浏览器可以自由决定何时以及如何下载资产。这可以独立于脚本执行的顺序。

现代浏览器通常会预取资产,以减少脚本下载时阻止 HTML 解析器的时间。

您首先看到3.js下载,因为浏览器扫描了浏览器中的资产并立即开始下载脚本。它只能在 HTML 解析器解析并执行其相应的内联script标记后开始下载1.js2.js

这意味着 HTML 解析器在下载 1.js2.js 时被阻止。如果像3.js一样直接包含所有脚本,则浏览器可能会并行预取三个脚本,从而使页面加载效率略高。

预提取实现是特定于浏览器的,因此您可能会在其他浏览器中看到不同的结果。