Script Tag - Async & Defer

Script Tag - async & defer

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.

Here's an article that explains the difference between async and defer: 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.

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.

You could put the scripts in the <head> tag and set them to defer and 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>.

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.

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.

What does async defer do when used together?

If you specify both, async takes precedence on modern browsers, while older browsers that support defer but not async will fallback to defer.

For the support table, check caniuse.com for async and for defer.


P/s: These attributes make only sense when using the script in the head portion of the page, and they are useless if you put the script in the body footer.

Can async and defer be used in the same script tags HTML?

To answer your question Yes

You can add both async and defer in the same script tag.
However it doesn't cancel out. The second one acts as a fallback if the first is unavailable.

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.

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

Running multiple scripts on async defer problems

With defer, the file gets downloaded asynchronously, but executed only when the document parsing is completed. Alswo with defer, scripts will execute in the same order as they are called. This makes defer the attribute of choice when a script depends on another script.

With async, the file gets downloaded asynchronously and then executed as soon as it’s downloaded.

In your case you can use defer so that the javascripts are executed when the document parsing is completed but not async if you want the dependencies to be preserved:

<script src="https://maps.googleapis.com/maps/api/js?key=__MY_KEY_HERE__...." defer></script>
<script src="/static/js/js-map-label.js" defer></script>

In practice, defer is used for scripts that need the whole DOM and/or their relative execution order is important. And async is used for independent scripts, like counters or ads. And their relative execution order does not matter.

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.

So if you use both modern browsers will only do async and won't perserve execution order.

Add defer or async attribute to dynamically generated script tags via JavaScript

There's no need to add async to your script tag, since that attribute is enabled by default for dynamic scripts.

As for defer, just as you change the src attribute in JavaScript, you can also enable that one like so:

var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
tag.defer = true;
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

Alternatively, you can use setAttribute() for this.

var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
tag.setAttribute('defer','');
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

How can I ensure that a defer script does not block other scripts (or async executes in order)?

Give the first script the async attribute, watch for its load event, and when that occurs, inject the second Jira script manually, so that Jira loads in order while also letting your own code run as soon as it can without waiting for Jira.

<script async src="https://url.to.jira/one"></script>
<script>
const firstJiraTag = document.currentScript.previousElementSibling;
firstJiraTag.addEventListener('load', () => {
document.body.appendChild(document.createElement('script')).src = "https://url.to.jira/two";
// once the above script fires its `load` event, both are loaded
});
// add an `error` listener to firstJiraTag if you want

// put your custom script here
// it will run as soon as this script tag runs,
// without waiting for the Jira above
window.ATL_JQ_PAGE_PROPS = {
"triggerFunction": function(showCollectorDialog) {
...
}
}
</script>

How to use defer/async attributes in script tag properly

If you want to use defer attribute in your external scripts you should use window.onload event because it fires after all page is loaded including deferred scripts. Try:

<!doctype html><html lang="en">
<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Defer attribute</title>
<!-- Bootstrap core CSS --> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.min.css" rel="stylesheet"> <style> .item { background: #ff3f4d; } h2 { color: #FFF; text-align: center; padding: 5rem 0; margin: 0; font-style: italic; font-weight: 300; } @media only screen and (min-width: 40.0625em) { h2 { font-size: 2.3125rem; } } </style> <script src="https://code.jquery.com/jquery-3.3.1.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/popper.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js" defer></script> <script> window.onload = function() { var owl = $('.owl-carousel'); owl.owlCarousel({ margin: 10, loop: true, responsive: { 0: { items: 1 }, 600: { items: 2 }, 1000: { items: 3 } } }); }; </script></head>
<body> <div class="container"> <h1 class="text-center">Hello World!</h1> <div class="owl-carousel"> <div class="item"> <h2>Swipe</h2> </div> <div class="item"> <h2>Drag</h2> </div> <div class="item"> <h2>Responsive</h2> </div> <div class="item"> <h2>CSS3</h2> </div> <div class="item"> <h2>Fast</h2> </div> <div class="item"> <h2>Easy</h2> </div> <div class="item"> <h2>Free</h2> </div> <div class="item"> <h2>Upgradable</h2> </div> <div class="item"> <h2>Tons of options</h2> </div> <div class="item"> <h2>Infinity</h2> </div> <div class="item"> <h2>Auto Width</h2> </div> </div> </div></body>
</html>

When to use async vs defer when loading scripts?

It's quite simple. You should use [async] for scripts which can be executed in any order, and [defer] for scripts which have to be executed after HTML is parsed.

For example, if you have a script that add social sharing icons next to your posts, and this script doesn't rely on any other script, you can use both [async] and [defer]. But if your scripts requires jQuery, you can't use [async], because if you do, it might turn out that it gets executed before jQuery is loaded and it breaks.

If all your scripts require jQuery, then you shouldn't use [async] at all. As for [defer], it depends on whether your scripts access DOM. For plugins it probably doesn't matter, but you'll probably need it for your own code.

If you wrap your scripts in $(document).ready();, you can use [defer] for scripts which don't have immediate effect (e.g. require user interaction).



Related Topics



Leave a reply



Submit