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
Get Cursor Position (In Characters) Within a Text Input Field
Using an HTML Button to Call a JavaScript Function
Html Form Readonly Select Tag/Input
Html Script Tag: Type or Language (Or Omit Both)
How to Autosize a Textarea Using Prototype
How to Open a Pdf File in an ≪Iframe≫
How to Store Arbitrary Data For Some HTML Tags
How to Add/Update an Attribute to an HTML Element Using JavaScript
Trigger Change Event When the Input Value Changed Programmatically
Set Custom Html5 Required Field Validation Message
Get File Size, Image Width and Height Before Upload
How Does Content Security Policy (Csp) Work
Resize Html5 Canvas to Fit Window
Disable Pasting Text into HTML Form
Passing Variable Through JavaScript from One HTML Page to Another Page