7

这是来自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>

我知道脚本标签会阻止并行下载,这就是为什么建议将它们放在底部的原因。

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

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

4

3 回答 3

9

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

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

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

对,因为规范需要该部分(在没有asyncordefer属性的情况下)。正如您的示例所示,在脚本运行之前,它甚至不一定确定脚本应该运行的顺序,因为脚本可能会插入另一个脚本。但它可以下载它们并准备好它们。

于 2012-05-21T07:58:13.243 回答
2

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

<script src="//other-domain.com/1.js"></script>

<script src="2.js"></script>

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

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

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

于 2014-07-09T17:11:06.473 回答
1

HTML5 规范说:

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

如果页面没有被解析,那么用户代理就无法知道哪些后续资源需要获取,因此严格遵守的浏览器在第一个资源实际执行之前应该无法获取更多资源。

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

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

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

于 2012-05-21T08:49:39.773 回答