Boost Page Speed with async and defer
Balwant Singh
Posted on July 8, 2023
JavaScript is an essential component in web programming, enabling interactivity and dynamic behaviour on web pages. While HTML and CSS handle the structure and aesthetics, JavaScript brings the page to life.
There are different ways to add JavaScript code to an HTML file. The most common method is to store the JavaScript code in a separate file with a .js extension. Then, you can load that file into the HTML using the script tag. This allows the browser to download and execute the JavaScript code.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Your Page Title</title>
<script src="your-script.js"></script>
</head>
<body>
<!-- Content of your webpage goes here -->
</body>
</html>
The issue with loading a JavaScript file in the <head>
When a browser encounters a <script src='...'>...</script>
tag in HTML, it pauses building the webpage and immediately executes the script. The browser must wait for the script to download, execute it, and only then can it continue processing the rest of the page.
This leads to 2 significant problems:
- Scripts cannot interact with or modify elements that appear after them in the HTML code. This means they can't add event handlers or make changes to elements lower down the page.
- If there is a large script at the top of the page, it causes a delay in displaying the page content. Users have to wait for the script to download and run before they can see the actual content of the page.
The Dirty Workaround:
So how do we fix this problem? One obvious but not-so-good fix is to move the script tag to the end of the <body>
tag
<body>
...all content is above the script...
<script src="your-script.js"></script>
</body>
However, this solution is not without its drawbacks. One of the issues is that the browser detects and begins downloading the script only after it has finished downloading the entire HTML document. This can result in noticeable delays, particularly for long HTML documents.
While this delay may go unnoticed by users with fast internet connections, it poses a problem for individuals with slower internet speeds or unreliable mobile connections.
Thankfully, there are two attributes available for the <script>
tag that provide solutions to this problem: defer
and async
.
Async Attribute
The
async
attribute is ignored if the<script>
tag has nosrc
.
<script async src="your-script.js"></script>
The async
attribute tells the browser not to wait for the script. Instead, the browser will continue to process the HTML, build DOM. The script downloads “in the background”, and execute once done.
Important Considerations When Using the async
Attribute
1) The async scripts execute in the load-first
order:
It does not guarantee the order of execution of the script. For instance, a smaller script small.js
goes second but probably downloads before long.js
, so small.js
executes first.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Your Page Title</title>
<script async src="long.js"></script>
<script async src="small.js"></script>
</head>
<body>
<!-- Content of your webpage goes here -->
</body>
</html>
2) DOMContentLoaded
event and async scripts don’t wait for each other:
When it comes to the order of execution, the DOMContentLoaded event and async scripts are independent of each other. The DOMContentLoaded event may occur before or after an async script, depending on factors such as the script's loading time and whether it is already present in the HTTP cache.
<script>
document.addEventListener('DOMContentLoaded', () => alert("DOM ready!"));
</script>
<script async src="your-script.js"></script>
Defer Attribute
The
defer
attribute is ignored if the<script>
tag has nosrc
.
<script defer src="your-script.js"></script>
The defer
attribute tells the browser not to wait for the script. Instead, the browser will continue to process the HTML, and build DOM. The script loads in the background, and then runs when the DOM is fully built.
Important Considerations When Using the defer
Attribute
1) defer
guarantees the order of execution of scripts just like regular scripts.
It guarantees the order of execution of the script. For instance, To enhance performance, browsers download scripts in parallel therefore smaller script small.js
goes second but probably downloads before long.js
, but it still waits and runs after long.js
executes..
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Your Page Title</title>
<script defer src="long.js"></script>
<script defer src="small.js"></script>
</head>
<body>
<!-- Content of your webpage goes here -->
</body>
</html>
2) DOMContentLoaded
event handler waits for the deferred script. It only triggers when the script is downloaded and executed.
<script>
document.addEventListener('DOMContentLoaded', () => alert("DOM ready!"));
</script>
<script defer src="your-script.js"></script>
When should I use what?
1) If the script is modular and does not depend on any other scripts such as independent third-party scripts like counters, and ads then use async
.
<!-- Google Analytics is usually added like this -->
<script async src="https://google-analytics.com/analytics.js"></script>
2) If the script relies upon or is relied upon by another script then use defer
.
3) If the script is small and is relied upon by an async script then use an inline script with no attributes placed above the async
scripts.
Dynamic Scripts
There is another important method of adding a script to a webpage. We can create a script element using JavaScript and add it to the document dynamically. Here's an example:
let script = document.createElement('script');
script.src = "your-script.js";
document.body.append(script);
Once the script is appended to the document, it starts loading immediately.
It's important to note that dynamic scripts behave as async
by default. This means that they will load asynchronously, potentially impacting the order of execution and interaction with other elements on the page.
To make it non-async, we can set
script.async = false
What if we put both async
and defer
attributes in the same script tag?
If you specify both, async
takes precedence on modern browsers, while older browsers that support defer
but not async
will fallback to defer
.
Posted on July 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 23, 2024