Javascript 脚本标签 - 异步和延迟

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10808109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:01:58  来源:igfitidea点击:

Script Tag - async & defer

javascripthtml

提问by Adam

I have a couple of questions about the attributes async& deferfor the <script>tag which to my understanding only work in HTML5 browsers.

我有一对夫妇的有关属性的问题asyncdefer<script>标签,该标签在HTML5的浏览器我的理解只有工作。

One of my sites has two external JavaScript files that currently sit just above the </body>tag; the first is jquerysourced from google and the second is a local external script.

我的一个站点有两个外部 JavaScript 文件,它们当前位于</body>标记的正上方;第一个是来自 google 的jquery,第二个是本地外部脚本。

With respects to site load speed

关于网站加载速度

  1. Is there any advantage in adding asyncto the two scripts I have at the bottom of the page?

  2. Would there be any advantage in adding the asyncoption to the two scripts and putting them at the top of the page in the <head>?

  3. Would this mean they download as the page loads?
  4. I assume this would cause delays for HTML4 browsers, but would it speed up page load for HTML5 browsers?
  1. 添加async到页面底部的两个脚本有什么好处吗?

  2. async选项添加到两个脚本并将它们放在<head>.

  3. 这是否意味着他们在页面加载时下载?
  4. 我认为这会导致 HTML4 浏览器的延迟,但它会加快 HTML5 浏览器的页面加载速度吗?

Using <script defer src=...

使用 <script defer src=...

  1. Would loading the two scripts inside <head>with the attribute deferthe same affect as having the scripts before </body>?
  2. Once again I assume this would slow up HTML4 browsers.
  1. <head>使用属性加载里面的两个脚本是否 与defer之前的脚本有相同的影响</body>
  2. 我再次假设这会减慢 HTML4 浏览器的速度。

Using <script async src=...

使用 <script async src=...

If I have two scripts with asyncenabled

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

  1. Would they download at the same time?
  2. Or one at a time with the rest of the page?
  3. Does the order of scripts then become a problem? For example one script depends on the other so if one downloads faster, the second one might not execute correctly etc.
  1. 他们会同时下载吗?
  2. 还是一次一个与页面的其余部分?
  3. 那么脚本的顺序会成为问题吗?例如,一个脚本依赖于另一个脚本,因此如果一个脚本下载速度更快,则第二个脚本可能无法正确执行等。

Finally am I best to leave things as they are until HTML5 is more commonly used?

最后,在 HTML5 更常用之前,我最好保持原样吗?

采纳答案by jfriend00

Keep your scripts right before </body>. Async can be used with scripts located there in a few circumstances (see discussion below). Defer won't make much of a difference for scripts located there because the DOM parsing work has pretty much already been done anyway.

</body>. 在某些情况下,异步可以与位于那里的脚本一起使用(参见下面的讨论)。Defer 不会对位于那里的脚本产生太大影响,因为 DOM 解析工作几乎已经完成。

Here's an article that explains the difference between async and defer: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/.

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

Your HTML will display quicker in older browsers if you keep the scripts at the end of the body right before </body>. So, to preserve the load speed in older browsers, you don't want to put them anywhere else.

如果您将脚本放在正文末尾的</body>. 因此,为了保持旧浏览器的加载速度,您不想将它们放在其他任何地方。

If your second script depends upon the first script (e.g. your second script uses the jQuery loaded in the first script), then you can't make them async without additional code to control execution order, but you can make them defer because defer scripts will still be executed in order, just not until after the document has been parsed. If you have that code and you don't need the scripts to run right away, you can make them async or defer.

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

You could put the scripts in the <head>tag and set them to deferand the loading of the scripts will be deferred until the DOM has been parsed and that will get fast page display in new browsers that support defer, but it won't help you at all in older browsers and it isn't really any faster than just putting the scripts right before </body>which works in all browsers. So, you can see why it's just best to put them right before </body>.

您可以将脚本放在<head>标签中并将它们设置为defer并且脚本的加载将被推迟,直到 DOM 被解析,这将在支持 defer 的新浏览器中获得快速页面显示,但它根本不会帮助您在较旧的浏览器中,它并不比将脚本</body>放在所有浏览器中都有效的前面快。因此,您可以理解为什么最好将它们放在</body>.

Async is more useful when you really don't care when the script loads and nothing else that is user dependent depends upon that script loading. The most often cited example for using async is an analytics script like Google Analytics that you don't want anything to wait for and it's not urgent to run soon and it stands alone so nothing else depends upon it.

当您真的不关心脚本何时加载并且用户依赖的任何其他内容都不依赖于该脚本加载时,异步会更有用。使用 async 最常被引用的例子是像 Google Analytics 这样的分析脚本,您不需要等待任何东西,而且不急于尽快运行,而且它是独立的,因此没有其他任何东西依赖于它。

Usually the jQuery library is not a good candidate for async because other scripts depend upon it and you want to install event handlers so your page can start responding to user events and you may need to run some jQuery-based initialization code to establish the initial state of the page. It can be used async, but other scripts will have to be coded to not execute until jQuery is loaded.

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

回答by Prasanth Bendra

This image explains normal script tag, async and defer

这张图片解释了普通的脚本标签、异步和延迟

enter image description here

在此处输入图片说明

  • Async scripts are executed as soon as the script is loaded, so it doesn't guarantee the order of execution (a script you included at the end may execute before the first script file )

  • Defer scripts guarantees the order of execution in which they appear in the page.

  • 异步脚本在脚本加载后立即执行,因此不保证执行顺序(您最后包含的脚本可能会在第一个脚本文件之前执行)

  • Defer 脚本保证了它们出现在页面中的执行顺序。

Ref this link : http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

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

回答by Dinesh

HTML5: async, defer

HTML5: async,defer

In HTML5, you can tell browser when to run your JavaScript code. There are 3 possibilities:

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

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

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

<script defer src="myscript.js"></script>
  1. Without asyncor defer, browser will run your script immediately, before rendering the elements that's below your script tag.

  2. With async(asynchronous), browser will continue to load the HTML page and render it while the browser load and execute the script at the same time.

  3. With defer, browser will run your script when the page finished parsing. (not necessary finishing downloading all image files. This is good.)

  1. 如果没有asyncor defer,浏览器将在渲染脚本标签下方的元素之前立即运行您的脚本。

  2. 使用async(异步),浏览器将继续加载 HTML 页面并呈现它,同时浏览器加载和执行脚本。

  3. 使用defer,浏览器将在页面完成解析时运行您的脚本。(没必要把所有的图片文件都下载完。这样就好了。)

回答by Zameer Khan

Both asyncand deferscripts begin to download immediately without pausing the parser and both support an optional onloadhandler to address the common need to perform initialization which depends on the script.

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

The difference between asyncand defercenters around when the script is executed. Each asyncscript 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 asyncscripts are not executed in the order in which they occur in the page. Whereas the deferscripts, 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 DOMContentLoadedevent.

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

Source & further details: here.

来源和更多细节:这里

回答by kamesh

Faced same kind of problem and now clearly understood how both will works.Hope this reference link will be helpful...

面临同样的问题,现在清楚地了解两者的工作原理。希望此参考链接会有所帮助...

Async

异步

When you add the async attribute to your script tag, the fol-low-ing will happen.

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

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Make par-al-lel requests to fetch the files.
  2. Con-tinue pars-ing the doc-u-ment as if it was never interrupted.
  3. Exe-cute the indi-vid-ual scripts the moment the files are downloaded.
  1. 发出并行请求以获取文件。
  2. 继续解析文档,就好像它从未被中断过一样。
  3. 在下载文件的那一刻执行单独的脚本。

Defer

推迟

Defer is very sim-i-lar to async with one major dif-fer-er-ence. Here's what hap-pens when a browser encoun-ters a script with the defer attribute.

Defer 与异步非常相似,但有一个主要区别。以下是浏览器遇到带有 defer 属性的脚本时发生的情况。

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Make par-al-lel requests to fetch the indi-vid-ual files.
  2. Con-tinue pars-ing the doc-u-ment as if it was never interrupted.
  3. Fin-ish pars-ing the doc-u-ment even if the script files have downloaded.
  4. Exe-cute each script in the order they were encoun-tered in the document.
  1. 发出并行请求以获取单个文件。
  2. 继续解析文档,就好像它从未被中断过一样。
  3. 即使已下载脚本文件,也要完成对文档的解析。
  4. 按照它们在文档中遇到的顺序执行每个脚本。

Reference :Difference between Async and Defer

参考:Async 和 Defer 的区别

回答by NavyaKumar

asyncand deferwill download the file during HTML parsing. Both will not interrupt the parser.

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

  • The script with asyncattribute will be executed once it is downloaded. While the script with deferattribute will be executed after completing the DOM parsing.

  • The scripts loaded with asyncdoes n't guarantee any order. While the scripts loaded with deferattribute maintains the order in which they appear on the DOM.

  • async下载后将执行带有属性的脚本。而带有defer属性的脚本将在完成 DOM 解析后执行。

  • 加载的脚本async不保证任何顺序。虽然加载了defer属性的脚本保持了它们在 DOM 上出现的顺序。

Use <script async>when the script does not rely on anything. when the script depends use .

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

Best solution would be add the at the bottom of the body.There will be no issue with blocking or rendering.

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

回答by mjfneto

I think Jake Archibald presented us some insights back in 2013 that might add even more positiveness to the topic:

我认为 Jake Archibald 早在 2013 年就向我们提供了一些见解,这些见解可能会为该主题增添更多积极性:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

https://www.html5rocks.com/en/tutorials/speed/script-loading/

The holy grail is having a set of scripts download immediately without blocking rendering and execute as soon as possible in the order they were added. Unfortunately HTML hates you and won't let you do that.

(...)

The answer is actually in the HTML5 spec, although it's hidden away at the bottom of the script-loading section. "The async IDL attribute controls whether the element will execute asynchronously or not. If the element's "force-async" flag is set, then, on getting, the async IDL attribute must return true, and on setting, the "force-async" flag must first be unset…".

(...)

Scripts that are dynamically created and added to the document are async by default, they don't block rendering and execute as soon as they download, meaning they could come out in the wrong order. However, we can explicitly mark them as not async:

圣杯是在不阻塞渲染的情况下立即下载一组脚本,并按照添加顺序尽快执行。不幸的是,HTML 讨厌你,不会让你这样做。

(……)

答案实际上在 HTML5 规范中,尽管它隐藏在脚本加载部分的底部。" async IDL 属性控制元素是否异步执行。如果设置了元素的“force-async”标志,则在获取时,async IDL 属性必须返回 true,并且在设置时,“force-async”标志必须首先取消设置......”。

(……)

默认情况下动态创建并添加到文档中的脚本是异步的,它们不会阻止渲染并在下载后立即执行,这意味着它们可能会以错误的顺序出现。但是,我们可以明确地将它们标记为非异步:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

This gives our scripts a mix of behaviour that can't be achieved with plain HTML. By being explicitly not async, scripts are added to an execution queue, the same queue they're added to in our first plain-HTML example. However, by being dynamically created, they're executed outside of document parsing, so rendering isn't blocked while they're downloaded (don't confuse not-async script loading with sync XHR, which is never a good thing).

The script above should be included inline in the head of pages, queueing script downloads as soon as possible without disrupting progressive rendering, and executes as soon as possible in the order you specified. “2.js” is free to download before “1.js”, but it won't be executed until “1.js” has either successfully downloaded and executed, or fails to do either. Hurrah! async-download but ordered-execution!

这为我们的脚本提供了纯 HTML 无法实现的混合行为。通过显式非异步,脚本被添加到一个执行队列中,与我们在第一个纯 HTML 示例中添加到的队列相同。但是,通过动态创建,它们在文档解析之外执行,因此在下载它们时不会阻止渲染(不要将非异步脚本加载与同步 XHR 混淆,这从来都不是一件好事)。

上面的脚本应该内嵌在页面的头部,在不中断渐进式渲染的情况下尽快排队脚本下载,并按照您指定的顺序尽快执行。“2.js”可以在“1.js”之前免费下载,但是直到“1.js”成功下载并执行或失败后才会执行。欢呼!异步下载但有序执行

Still, this might not be the fastest way to load scripts:

不过,这可能不是加载脚本的最快方式:

(...) With the example above the browser has to parse and execute script to discover which scripts to download. This hides your scripts from preload scanners. Browsers use these scanners to discover resources on pages you're likely to visit next, or discover page resources while the parser is blocked by another resource.

We can add discoverability back in by putting this in the head of the document:

(...) 对于上面的示例,浏览器必须解析并执行脚本以发现要下载的脚本。这会向预加载扫描程序隐藏您的脚本。浏览器使用这些扫描器来发现您接下来可能访问的页面上的资源,或者在解析器被另一个资源阻止时发现页面资源。

我们可以通过把它放在文档的头部来增加可发现性:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

This tells the browser the page needs 1.js and 2.js. link[rel=subresource] is similar to link[rel=prefetch], but with different semantics. Unfortunately it's currently only supported in Chrome, and you have to declare which scripts to load twice, once via link elements, and again in your script.

Correction:I originally stated these were picked up by the preload scanner, they're not, they're picked up by the regular parser. However, preload scanner could pick these up, it just doesn't yet, whereas scripts included by executable code can never be preloaded. Thanks to Yoav Weiss who corrected me in the comments.

这告诉浏览器页面需要 1.js 和 2.js。link[rel=subresource] 与 link[rel=prefetch] 类似,但语义不同。不幸的是,它目前仅在 Chrome 中受支持,您必须声明要加载两次的脚本,一次是通过链接元素,一次是在您的脚本中。

更正:我最初说这些是由预加载扫描器拾取的,它们不是,它们是由常规解析器拾取的。然而,预加载扫描器可以选择这些,只是还没有,而可执行代码包含的脚本永远不能被预加载。感谢 Yoav Weiss 在评论中纠正了我。

回答by Charles Owen

It seems the behavior of defer and async is browser dependent, at least on the execution phase. NOTE, defer only applies to external scripts. I'm assuming async follows same pattern.

似乎 defer 和 async 的行为取决于浏览器,至少在执行阶段是这样。注意, defer 仅适用于外部脚本。我假设异步遵循相同的模式。

In IE 11 and below, the order seems to be like this:

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

  • async (could partially execute while page loading)
  • none (could execute while page loading)
  • defer (executes after page loaded, all defer in order of placement in file)
  • 异步(可以在页面加载时部分执行)
  • 无(可以在页面加载时执行)
  • 延迟(在页面加载后执行,所有延迟都按照文件中的放置顺序)

In Edge, Webkit, etc, the async attribute seems to be either ignored or placed at the end:

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

  • data-pagespeed-no-defer (executes before any other scripts, while page is loading)
  • none (could execute while page is loading)
  • defer (waits until DOM loaded, all defer in order of placement in file)
  • async (seems to wait until DOM loaded)
  • data-pagespeed-no-defer(在页面加载时在任何其他脚本之前执行)
  • 无(可以在页面加载时执行)
  • defer(等待 DOM 加载,所有都按照文件中的放置顺序进行延迟)
  • 异步(似乎要等到 DOM 加载)

In newer browsers, the data-pagespeed-no-defer attribute runs before any other external scripts. This is for scripts that don't depend on the DOM.

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

NOTE: Use defer when you need an explicit order of execution of your external scripts. This tells the browser to execute all deferred scripts in order of placement in the file.

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

ASIDE: The size of the external javascripts did matter when loading...but had no effect on the order of execution.

旁白:加载时外部 javascript 的大小确实很重要……但对执行顺序没有影响。

If you're worried about the performance of your scripts, you may want to consider minification or simply loading them dynamically with an XMLHttpRequest.

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