2012-05-21 69 views
4

这是从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过吗?

抑或是向前看,尽快开始下载的所有脚本地(并行),只是延缓每个脚本的执行直到前一个已经执行完毕?

回答

8

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

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

抑或是向前看,尽快启动所有的脚本下载越好(并行),只是延缓执行每个脚本直到前一个已经执行完毕?

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

+0

这是否意味着像JavaScript异步加载技术这样的最佳实践在当今较新的浏览器中不那么重要?他们是否只记得文档中出现的外部脚本链接在并行下载后执行它们的顺序?这似乎是因为如果我看看Chrome开发者工具/资源面板,大量的js文件同时开始下载并且不会像书籍中的屏幕截图一样被阻止(例如,“更快的网站”)显示为例。 – malthoff

+0

@malthoff:*“他们是否记得在文档中出现的外部脚本链接在并行下载后执行它们的顺序?”*正确。如果你有(说)五个脚本,但是它们加载其中两个的顺序并不重要,你可以标记那些'async',在这种情况下(在现代浏览器上),只要他们'重新下载,不管顺序如何。 –

+0

“但它可以下载并准备好它们。”但事实上,浏览器是这样做的吗? – callum

1

HTML5规范表示:

如果既没有属性[即async and defer]存在,那么在用户代理继续解析 页面之前,脚本被取出并立即执行。

如果页面无法解析,那么用户代理无法知道哪些后续的资源获取需要,因此严格遵循规则的浏览器不应该能够直到第一个已实际执行来获取更多的资源。

为了说明为什么这是有道理的,假设第一个脚本包含

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

没有匹配的注释关闭,则后面的标记,该脚本将成为注释的一部分,直到下一个-->就是一切遇到。这可能会导致跳过一个或多个资源引用。

1

我发现这个细节更合适这个问题的答案,复制下面的内容从http://www.html5rocks.com/en/tutorials/speed/script-loading/提到它的更多细节。

< SCRIPT SRC = " //other-domain.com/1.js " > < /脚本>

< SCRIPT SRC = " 2.js " > < /脚本>

稀释,幸福简单。在这里,浏览器将同时下载两个脚本并尽快执行它们,以维护它们的顺序。直到“1.js”执行完成(或不执行),“2.js”才会执行,“1.js”将不会执行,直到前面的脚本或样式表执行完成等等。不幸的是,浏览器阻止了进一步的页面渲染,而这一切正在发生。这是由于“网络第一时代”的DOM API允许字符串被附加到解析器正在咀嚼的内容上,如document.write。较新的浏览器将继续在后台扫描或解析文档,并触发它可能需要的外部内容(js,图像,css等)的下载,但渲染仍然被阻止。

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