我有几个关于<script>标签的async和defer属性的问题,据我的理解,它只在HTML5浏览器中工作。
我的一个站点有两个外部JavaScript文件,目前位于</body>标记上方;第一个是来自谷歌的jquery,第二个是一个本地外部脚本。
在网站加载速度方面
在我在页面底部的两个脚本中添加async是否有任何优势?
在这两个脚本中添加async选项并将它们放在<head>的页面顶部是否有任何优势?
这是否意味着他们会在页面加载时下载?
我认为这会导致HTML4浏览器的延迟,但是它会加速HTML5浏览器的页面加载吗?
使用<script defer src=…
在<head>中加载带有属性的两个脚本是否与在</body>之前加载脚本具有相同的影响?
同样,我认为这会降低HTML4浏览器的速度。
使用<script async src=…
如果我有两个脚本异步启用
他们会同时下载吗?
还是一页一页地看?
脚本的顺序会成为问题吗?例如,一个脚本依赖于另一个脚本,所以如果一个脚本下载得更快,第二个脚本可能无法正确执行等等。
最后,在HTML5得到更广泛的应用之前,我是否应该保持现状?
面对同样的问题,现在清楚地了解两者将如何工作。希望这个参考链接会有帮助…
异步
当您将async属性添加到脚本标记时,将发生以下情况。
<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
发出并行请求来获取文件。
继续解析文档,就像它从未被打断过一样。
文件下载后立即执行各个脚本。
推迟
延迟与异步非常相似,但有一个主要区别。下面是浏览器遇到带有defer属性的脚本时会发生的情况。
<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
进行并行请求以获取单个视频文件。
继续解析文档,就像它从未被打断过一样。
即使已经下载了脚本文件,也要完成文档解析。
按照文档中出现的顺序执行每个脚本。
参考:异步和延迟的区别
async和defer脚本都立即开始下载,而不需要暂停解析器,并且都支持可选的onload处理程序,以满足执行初始化(依赖于脚本)的常见需求。
The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) that async scripts are not executed in the order in which they occur in the page. Whereas the defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document’s DOMContentLoaded event.
来源和更多细节:这里。
保持你的脚本在</body>之前。Async可以在一些情况下与位于那里的脚本一起使用(参见下面的讨论)。延迟不会对位于那里的脚本产生太大影响,因为DOM解析工作基本上已经完成了。
这里有一篇文章解释了async和defer的区别:http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/。
如果你把脚本放在正文的末尾</body>之前,你的HTML在旧的浏览器中会显示得更快。所以,为了保持旧浏览器的加载速度,你不希望把它们放在其他地方。
如果你的第二个脚本依赖于第一个脚本(例如,你的第二个脚本使用了第一个脚本中加载的jQuery),那么如果没有额外的代码来控制执行顺序,你就不能使它们异步,但是你可以使它们延迟,因为延迟脚本仍然会按顺序执行,只是直到文档被解析之后。如果您有这些代码,并且不需要立即运行脚本,则可以将它们设置为异步或延迟。
你可以把脚本放在<head>标签,并将它们设置为延迟,脚本的加载将被延迟,直到DOM被解析,这将在支持延迟的新浏览器中获得快速页面显示,但在旧的浏览器中,这对你没有任何帮助,它并没有比把脚本放在</body>之前更快,这在所有浏览器中都有效。所以,你可以明白为什么最好把它们放在</body>之前。
当你真的不关心脚本何时加载,并且没有其他用户依赖于脚本加载时,Async更有用。最常被引用的使用async的例子是像谷歌analytics这样的分析脚本,你不希望等待任何东西,也不急于很快运行,它是独立的,所以没有其他东西依赖于它。
通常,jQuery库不是async的最佳候选,因为其他脚本依赖于它,并且您希望安装事件处理程序,以便您的页面可以开始响应用户事件,并且您可能需要运行一些基于jQuery的初始化代码来建立页面的初始状态。它可以异步使用,但其他脚本必须被编码为在加载jQuery之前不执行。
看起来defer和async的行为是依赖于浏览器的,至少是在执行阶段。说明“defer”仅适用于外部脚本。我假设async遵循相同的模式。
在IE 11及以下版本中,顺序是这样的:
异步(可以在页面加载时部分执行)
无(可以在页面加载时执行)
延迟(在页面加载后执行,所有延迟在文件中的位置顺序)
在Edge, Webkit等中,async属性似乎要么被忽略,要么被放在末尾:
data-page - speed-no-defer(在加载页面时,在任何其他脚本之前执行)
无(可以在页面加载时执行)
延迟(等待DOM加载,所有延迟在文件中的位置顺序)
async(似乎等待DOM加载)
在较新的浏览器中,data-pagespeed-no-defer属性在任何其他外部脚本之前运行。这适用于不依赖于DOM的脚本。
注意:当您需要明确外部脚本的执行顺序时,请使用defer。这告诉浏览器按照在文件中的位置顺序执行所有延迟脚本。
旁白:外部javascript的大小在加载时确实很重要……但对执行顺序没有影响。
如果您担心脚本的性能,那么您可能需要考虑缩小或使用XMLHttpRequest动态加载它们。