async vs defer attributes in Javascript
Introduction
A script
tag is used to load javascript inside a web browser. async
and defer
are the boolean attributes used along with the script
tag to load the external scripts efficiently into the web page. In this article, we will cover the following scenarios of how a javascript file can be loaded using:
script
tag.script
tag withasync
attribute.script
tag withdefer
attribute.
What happens when you load a web page?
When you load a web page, there are 2 things that are happening inside the browser:
- HTML parsing.
- Loading of the scripts.
Loading of the script contains two parts:
- Fetching the script from the network.
- Actually executing the script line by line - know as thread of execution.
Using script
tag
When your browser is parsing the HTML line by line building the DOM (Document Object Model) and if it encounters a script
tag, It pauses the parsing of HTML, fetches the script from the network, and executes the script inside the browser. The rest of the DOM is built after the script is loaded and executed.
<html>
<head>
<title>My Webpage</title>
<script src="./main/javascript/helloWorld.js"></script>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
Here,
- HTML parsing starts from line 1 and the browser starts building the DOM.
- At line 4, when the browser encounters the
script
tag, it pauses the parsing. It fetches the file from the network and executes it line by line. After the execution of the script is completed, it resumes the parsing and moves onto thebody
tag to build the rest of the DOM.
This lead to two important issues:
- They can't add event handlers, etc as the DOM is not fully built.
- It blocks the page. Users can't see the rest of the page content until it downloads and runs the script.
Both of these issues can be solved by specifying the script
tag at the end of the body
tag but that's not very efficient. We have async
and defer
attributes for this use case.
Using async
attribute
With the async
attribute, whenever the HTML parsing is going on, the scripts are fetched from the network asynchronously. After the scripts are loaded and available inside the browser, the scripts are executed then and there. After the scripts are executed, the rest of the HTML parsing is done. Here, the loading of the scripts is done parallelly with HTML parsing unlike in the normal script
tag.
Let's consider an example where there are two files - long.js and short.js. Consider long.js script is heavier than short.js script:
<html>
<head>
<title>My Webpage</title>
<script async src="./main/javascript/long.js"></script>
<script async src="./main/javascript/short.js"></script>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
- At line 1, HTML parsing is started.
- At line 4, the browser encounters the
script
tag with theasync
attribute. - The long.js script is being fetched asynchronously in parallel and control moves to the next line.
- The short.js script is then fetched asynchronously in parallel and controls move to the next line.
- Whichever files are loaded first is executed. Therefore, even though long.js is encountered first, short.js is loaded first and executed.
- The rest of the DOM is built.
Using defer
attribute
It is similar to the async
attribute where the scripts are loaded in parallel. The difference being the scripts are only executed when the HTML parsing is fully complete and the DOM is built.
<html>
<head>
<title>My Webpage</title>
<script defer src="./main/javascript/long.js"></script>
<script defer src="./main/javascript/short.js"></script>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
- At line 1, HTML parsing is started.
- At line 4, the browser encounters the
script
tag with thedefer
attribute. - The long.js script is being fetched in parallel and control moves to the next line.
- The short.js script is then fetched in parallel and controls move to the next line.
- The HTML parsing is done and DOM is built.
- Execution of scripts.
Note: Even though short.js is fetched first, the execution order is maintained. In this case, long.js will execute before short.js.
When to use what
- Using
async
attribute doesn't guarantee the order of execution of scripts. Async scripts are mostly used to load the third-party scripts that are not dependent on each other like google analytics, etc. - Use
defer
attribute when scripts are dependent on each other. These scripts are mostly used as they give the best of both worlds - execution in order and parallel fetching of scripts while HTML parsing.
Summary
- In normal
script
tags, whenever the scripts are encountered, the script is loaded and executed then and there, and the rest of HTML parsing is done. - With the
async
attribute, scripts are fetched parallelly along with HTML parsing, and as soon as scripts are loaded they are executed. - With the
defer
attribute, scripts are fetched parallelly along with HTML parsing, and as soon as HTML parsing is done, they are executed.
That's pretty much the different efficient ways to load javascript files into the web browser. If you have any feedback or suggestions, feel free to reach out to me on Twitter or LinkedIn.
Developer Advocate, Hashnode
Ah. I love this article.
Thanks for sharing Vinit Raut.
learned something new today! thnx! But: can you explain for newbies like me the why in "specifying the script tag at the end of the body tag but that's not very efficient"
Thank you for sharing your feedback! By specifying the script at the end of the body tag, the script will be loaded and executed at the end. You can optimize the fetching of scripts while HTML is parsing by specifying async
and defer
and also control when they should run.
Very nice article! Clear and concise. I'd like to ask if both properties async
and defer
could be used on the same script
tag
I am glad you liked the article! You can use both simultaneously but is not recommended. async
has a higher priority than defer
. Depending upon the use case and dependencies of the scripts, you can use async
and defer
accordingly.
I write daily web development tips that help you become a more efficient developer. 👨💻⚡️
Nice article! Good understanding between async and defer.
☝ UI/UX/ML | ✍️ Technology Blogger | 🎤 Speaker
Good one Vinit Raut!
Thank you Tapas Adhikary. Really appreciated your feedback before I published this article. :)
Nice article. Learnt something new today about script tags. It feels good to read such short but information packed articles. Keep it up.
Comments (11)