Defer & Async Attributes in Javascript
The default way of treating a <scipt/>
tag by a browser is to pause creating DOM (Document Object Model) and start loading and executing the resource of script
but this behaviour leads to two important issues:
The script does not have access to the complete DOM since its creation was paused midway which results in not being able to modify (add handlers) to the DOM properly
Since
<script>
blocks the browser from creating DOM which results in turning UI unusable/non-interactive
Representation of first issue:
Code:
<html>
<body>
<p>Content loaded before execution of script</p>
<script src="index.js"></script>
<p id="dynamic_header">Content loaded after execution of script</p>
</body>
</html>
document.getElementById("dynamic_header").innerHTML ="The content has been modified";
Even after having a script that is supposed to change the content of <p id="dynamic_header">...</p>
there is no change which by now we understand is due to the reason that the script was executed even before this part of the DOM was even created.
Representation of second issue:
Code:
<html>
<head>
<title>Blog 1</title>
<meta charset="UTF-8" />
<script> alert("hello world")</script>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Here we witness how the script blocks the DOM formation when the script is executing.
Note: this behaviour is witnessed by both inline & external scripts
To tackle these issue there are two <script>
attributes that solve the problem for us: defer
and async
.
defer
The defer
attribute which is associated with <script>
tag tells the browser to not block the creation of DOM when browser comes across script
tag but to load the resources from<script>
tag parallelly in background and once the DOM is completely created then execute the script
at the end. This method fixes our issue regarding blocking the creation of DOM and prevents leading to a condition where script
wants to associate a handler to an DOM which is not created yet.
Let us modify our previous code for changing content of <p id="dynamic_header">...</p>
but this time we use defer
attribute Code:
<html>
<body>
<p>Content loaded before execution of script</p>
<script defer src="index.js"></script>
<p id="dynamic_header">Content loaded after execution of script</p>
</body>
This time the content did change and this was possible because we used defer
attribute.
async
The async
attribute is somewhat similar to defer
in a way that both of them make script non-blocking and resources are loaded parallelly while DOM is being created but there is also a significant difference between both of them. Unlike defer
, async
does not execute once all the DOM is created but it executes immediately after all the resources from the <script>
tag have been loaded.
Note: defer & async attribute only works for external scripts
Discussion Point
Looking at defer
attribute, it basically executes script tags once DOM in created. So, why don't we just use script
tag at then end of our <body/>
which will also execute after entire DOM is created? Well, this might sound right but it does come with it's own problems. With defer
attribute script is loaded in the background while the DOM in being created but in this way around, the script will start loading after DOM has been created which is result in delay.
Subscribe to my newsletter
Read articles from Nabeel Boda directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by