可以在 HTML 标记上同时使用异步和延迟属性吗?

我想同时使用 deferasync加载以下 JavaScript 代码:

<script defer async src="/js/somescript.js"></script>

由于 Internet Explorer 5.5 + 支持 defer,正如你在 CanIUse.com中看到的那样,如果不能使用异步的话,我想优雅地退回到使用 defer。我认为异步应该在可用的时候使用,但是直到 Internet Explorer 10才支持。

因此,我的问题是上面的代码是有效的 HTML 吗?如果没有,当 async不可用时,是否可以使用 JavaScript 在脚本上优雅地退回到使用 defer来创建这种情况?

26825 次浏览

Yes, its valid HTML and it will work like expected.

Any W3C compliant browser will recognize the async attribute and treat the script properly, whereas legacy IE versions will recognize the defer attribute.

Since both attributes are boolean you don't have to assign any value.

From the specification: https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behavior instead of the synchronous blocking behavior that is the default.

(Check the reference link below to see a visual representation of the differences between normal scripts and scripts with defer and async)


References:

The question is, what would you expect it to do? If both async and defer are present I would expect the script to be deferred and only executed after DOMContentLoaded when the browser is idle, but if I'm reading the specification right it looks like defer is ignored if async is set and the script is loaded asynchronously, so will execute as soon as it's available, which may well be before DOMContentLoaded and may block other resources.

There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.

https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async

Unfortunately defer is ignored when async specified, and async always have higher priority.

And personally I think that it's very bad that defer is ignored. Let's imagine situation when we would like to have some JS initialized ASAP, even before loading of the page content. But we want this script initialized BEFORE the rest of scripts which requires it. It should be first in defer queue. But, unfortunately, this will not work:

<!-- we want "jQuery" ASAP and still in "defer" queue. But defer is ignored. -->
<script src="jquery.min.js" async defer></script>


<!-- this doesn't blocks the content and can wait the full page load, but requires "jQuery" -->
<script src="some_jquery_plugin.min.js" defer></script>

In this sample the "some_jquery_plugin.min.js" can be loaded and executed before the load of jQuery, and will fail. :(

So there is 2 ways to solve the problem: either use only defer directive, or merge all depending javascript files into single JS.

Actually, there is a misconception in most comments here. People don´t seem to know that DEFER also loads the code in parallel, just like ASYNC. But it waits to execute after DOM loads (but before DOMContentLoaded executes), while ASYNC runs it immediately after loading, before DOM loads. Since BOTH ASYNC and DEFER load code in parallel, there would be no need to use both together (but to deal with legacy, maybe).

Yes, you can use both attributes but you need to use defer or async, not both. For more see the comparison and use one based on your need.

defer attribute: First it will download the script file and then wait of html parsing. After the end of html parsing, script will execute. In other words, It will guarantee all the scripts will execute after the html parsing.

Defer attribute is useful when script is using for DOM manipulations. Means script will apply on document html.

async attribute: It will download the script file and execute without wait the end of html parsing. In other words, It will not guarantee all the scripts will execute after the html parsing.

Async attribute is useful when script is not using for DOM manipulation. Some time you need script only for server side operations or for handling cache or cookie but not for DOM manipulations. Means script is not related to the used html.

enter image description here