运行脚本标签是否阻止其他脚本标签下载?

时间:2012-05-21 07:56:01

标签: javascript html optimization script-tag

这来自HTML5 Boilerplate中的 index.html ,就在</body>标记之前:

<!-- JavaScript at the bottom for fast page loading: http://developer.yahoo.com/performance/rules.html#js_bottom -->

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.7.2.min.js"><\/script>')</script>

<!-- scripts concatenated and minified via build script -->
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<!-- end scripts -->

<!-- Asynchronous Google Analytics snippet. Change UA-XXXXX-X to be your site's ID.
     mathiasbynens.be/notes/async-analytics-snippet -->
<script>
  var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
  (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
  g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
  s.parentNode.insertBefore(g,s)}(document,'script'));
</script>

我知道脚本标记可以阻止并行下载,这就是it's recommended to put them at the bottom

的原因

我的问题:浏览器是否真的等待jQuery完全下载并执行,甚至开始下载plugins.js然后script.js

或者它是否向前看并尽快(并行)启动所有脚本下载,并且只是延迟每个脚本的执行,直到前一个脚本为止完成了执行?

3 个答案:

答案 0 :(得分:8)

  

我的问题:浏览器是否真的等待jQuery完全下载并执行,甚至开始下载plugins.js然后script.js

它可能会也可能不会,但可能不会;浏览器尝试(在限制范围内)并行化下载以快速加载页面。

  

或是它向前看并尽快开始下载所有脚本(并行),只是延迟每个脚本的执行直到前一个脚本完成执行?

是的,因为该部分是required by the specification(在asyncdefer属性的缺席中)。正如您的示例所示,在脚本运行之前,它甚至无法确定脚本应该运行的顺序,因为脚本可能会插入另一个脚本。但它可以下载并准备好它们。

答案 1 :(得分:2)

我发现这个详细信息更适合这个问题的答案,复制到http://www.html5rocks.com/en/tutorials/speed/script-loading/下面的内容中,请参阅更多详情。

&lt; script src =&#34; // other-domain.com/1.js"></script>

&lt; script src =&#34; 2.js&#34;&gt;&lt; / script&gt;

啊,幸福的简单。在这里,浏览器将并行下载两个脚本并尽快执行它们,维护它们的顺序。 “2.js”将在“1.js”执行(或未能执行)之前执行,“1.js”将不执行,直到前一个脚本或样式表执行等等。

不幸的是,浏览器会阻止进一步呈现页面,而这一切都在发生。这是因为来自“网络的第一个时代”的DOM API允许将字符串附加到解析器正在咀嚼的内容上,例如document.write。较新的浏览器将继续在后台扫描或解析文档,并触发下载可能需要的外部内容(js,图像,CSS等),但渲染仍然被阻止。

这就是为什么性能世界的伟大和善意建议将脚本元素放在文档的末尾,因为它会阻止尽可能少的内容。不幸的是,这意味着在下载所有HTML之前,浏览器不会看到您的脚本,此时它开始下载其他内容,例如CSS,图像和iframe。现代浏览器非常聪明,可以优先使用JavaScript而不是图像,但我们可以做得更好。

答案 2 :(得分:1)

HTML5规范说:

  

如果两个属性都没有[即存在async和defer],然后获取脚本   在用户代理继续解析之前立即执行   页。

如果未解析页面,则用户代理无法知道哪些后续资源需要提取,因此严格符合要求的浏览器在第一次实际执行之前不应该获取更多资源。

要了解为什么这有意义,请想象第一个脚本包含

document.write("<!--"); 

没有匹配的注释闭包,那么标记中脚本后面的所有内容都将成为注释的一部分,直到遇到下一个-->。这可能会导致跳过一个或多个资源引用。