脚本标记 - 异步和延迟

问题描述 投票:381回答:7

关于async标签的defer<script>属性,我有几个问题,据我所知,只能在HTML5浏览器中使用。

我的一个网站有两个外部JavaScript文件,目前位于</body>标签上方;第一个是来自谷歌的,第二个是本地外部脚本。

关于网站加载速度

  1. async添加到页面底部的两个脚本中是否有任何优势?
  2. async选项添加到两个脚本并将它们放在<head>页面的顶部是否有任何优势?
  3. 这是否意味着他们下载页面加载?
  4. 我认为这会导致HTML4浏览器的延迟,但是它会加速HTML5浏览器的页面加载吗?

使用<script defer src=...

  1. <head>中的两个脚本加载到defer属性与</body>之前的脚本相同吗?
  2. 我再次假设这会降低HTML4浏览器的速度。

使用<script async src=...

如果我有两个启用了async的脚本

  1. 他们会同时下载吗?
  2. 或者与页面的其余部分一次一个?
  3. 脚本的顺序是否会成为问题?例如,一个脚本依赖于另一个脚本,因此如果下载速度更快,则第二个脚本可能无法正确执行等。

最后,我最好保留原样,直到HTML5更常用?

javascript html5
7个回答
349
投票

</body>之前保持你的脚本正确。在某些情况下,Async可以与位于那里的脚本一起使用(参见下面的讨论)。 Defer不会对位于那里的脚本产生很大的影响,因为DOM解析工作已经完成了很多工作。

这是一篇解释异步和延迟之间差异的文章:http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/

如果您在</body>之前将脚本保留在正文末尾,那么您的HTML将在旧版浏览器中更快地显示。因此,为了保持旧版浏览器的加载速度,您不希望将它们放在其他任何位置。

如果您的第二个脚本依赖于第一个脚本(例如,您的第二个脚本使用第一个脚本中加载的jQuery),那么您无法在没有其他代码来控制执行顺序的情况下使它们异步,但您可以使它们延迟,因为延迟脚本将仍然按顺序执行,直到文档被解析后才执行。如果您拥有该代码并且不需要立即运行脚本,则可以使它们异步或延迟。

您可以将脚本放在<head>标记中并将它们设置为defer,并且脚本的加载将推迟到解析DOM并且将在支持延迟的新浏览器中显示快速页面,但它不会帮助您在旧版浏览器中,它实际上并不比仅在所有浏览器中运行的</body>之前放置脚本快。所以,你可以看到为什么最好把它们放在</body>之前。

当您在脚本加载时并不关心时,Async会更有用,并且用户所依赖的任何其他内容都不依赖于该脚本加载。最常被引用的使用异步的示例是像Google Analytics这样的分析脚本,您不需要等待任何事情,并且不急于即将运行并且它是独立的,因此没有其他任何依赖它。

通常jQuery库不适合async,因为其他脚本依赖它并且你想安装事件处理程序,所以你的页面可以开始响应用户事件,你可能需要运行一些基于jQuery的初始化代码来建立初始状态的页面。它可以用作异步,但是其他脚本必须编码才能在加载jQuery之前执行。


615
投票

此图像解释了正常的脚本标记,异步和延迟

enter image description here

  • 加载脚本后立即执行异步脚本,因此不保证执行顺序(最后包含的脚本可能在第一个脚本文件之前执行)
  • 延迟脚本保证它们在页面中出现的执行顺序。

参考链接:http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html


193
投票

HTML5:asyncdefer

在HTML5中,您可以告诉浏览器何时运行JavaScript代码。有三种可能性:

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

<script async src="myscript.js"></script>

<script defer src="myscript.js"></script>
  1. 如果没有asyncdefer,浏览器将立即运行您的脚本,然后再渲染脚本标记下方的元素。
  2. 使用async(异步),浏览器将继续加载HTML页面并在浏览器加载时呈现它,同时执行脚本。
  3. 使用defer,浏览器将在页面完成解析后运行您的脚本。 (没必要完成下载所有图像文件。这很好。)

24
投票

asyncdefer脚本都会立即开始下载而不会暂停解析器,并且都支持可选的onload处理程序,以满足执行初始化的常见需求,这取决于脚本。

asyncdefer之间的区别在于脚本执行时。每个async脚本在完成下载之后和窗口加载事件之前的第一次机会执行。这意味着async脚本可能(并且很可能)不按页面中出现的顺序执行。而另一方面,defer脚本保证按照它们在页面中出现的顺序执行。解析完成后,但在文档的DOMContentLoaded事件之前,执行开始。

来源及进一步细节:here


22
投票

面对同样的问题,现在清楚地了解两者是如何工作的。希望这个参考链接会有所帮助......

异步

将async属性添加到脚本标记时,将发生以下情况。

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. 进行并行请求以获取文件。
  2. 继续解析文档,好像它从未被中断过一样。
  3. 下载文件时执行各个脚本。

推迟

Defer非常类似于一个主要差异的异步。以下是浏览器遇到带有defer属性的脚本时发生的情况。

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. 进行并行请求以获取单个文件。
  2. 继续解析文档,好像它从未被中断过一样。
  3. 即使脚本文件已下载,也要完成解析文档。
  4. 按照文档中遇到的顺序执行每个脚本。

参考:Difference between Async and Defer


1
投票

似乎延迟和异步的行为依赖于浏览器,至少在执行阶段。注意,延迟仅适用于外部脚本。我假设异步遵循相同的模式。

在IE 11及更低版本中,顺序似乎是这样的:

  • async(在页面加载时可以部分执行)
  • 无(可在页面加载时执行)
  • 延迟(在页面加载后执行,所有按顺序放置在文件中)

在Edge,Webkit等中,async属性似乎被忽略或放在最后:

  • data-pagespeed-no-defer(在加载页面之前,在任何其他脚本之前执行)
  • 无(可在页面加载时执行)
  • 延迟(等待加载DOM,所有按顺序放入文件中)
  • async(似乎等到DOM加载)

在较新的浏览器中,data-pagespeed-no-defer属性在任何其他外部脚本之前运行。这适用于不依赖于DOM的脚本。

注意:当您需要明确执行外部脚本的顺序时,请使用延迟。这告诉浏览器按照放置在文件中的顺序执行所有延迟脚本。

ASIDE:外部javascripts的大小在加载时很重要......但对执行顺序没有影响。

如果您担心脚本的性能,可能需要考虑缩小或简单地使用XMLHttpRequest动态加载它们。


-1
投票

asyncdefer将在HTML解析期间下载该文件。两者都不会中断解析器。

  • 具有async属性的脚本将在下载后执行。具有defer属性的脚本将在完成DOM解析后执行。
  • 使用async加载的脚本不保证任何订单。使用defer属性加载的脚本维护它们在DOM上的显示顺序。

当脚本不依赖任何东西时使用<script async>。当脚本依赖使用时。

最好的解决方案是添加在body的底部。阻塞或渲染没有问题。

UPDATE

答案已根据评论予以纠正。

© www.soinside.com 2019 - 2024. All rights reserved.