Script Loading using Async and Defer

18 / Mar / 2025 by Aayush Mehta 0 comments

Introduction

When it comes to creating production-ready websites, JavaScript is an essential element. It brings websites to life by adding interactivity, dynamism, and a user-friendly experience. Whether you’re looking to implement real-time location tracking for a food delivery app or track user traffic with a bar graph on an admin dashboard, JavaScript is the key to making these features possible.

But have you ever wondered how these features are loaded in our application? These features are loaded using the <scripts> tag. Scripts are loaded to ensure optimal performance for your website or application. The way the script is loaded can significantly impact page loading times and overall user experience.

There are two main methods to load a script: async and defer. Both techniques allow scripts to execute without blocking other important processes, like content loading or page rendering. In this blog, we’ll dive into these two approaches and explore how they can help enhance your website’s performance.

Default way of loading a script

Let’s begin by understanding how scripts are loaded by default, without using the async or defer attributes. When linking an external script to an HTML file, we typically use the <script> tag, which can be placed either inside the <head> or the <body>.

By default, when neither the async nor defer attribute is used, the script is downloaded and executed right away, blocking the HTML parsing process until the script has finished loading and executing.

Let’s take a look at an example to better understand this behavior:

<!----============Code============---->
<p>content before script...</p>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=myMap"></script>
<p>content after script...</p>
Default Behaviour

Default behaviour

Let’s break down what happens in the code. Imagine you are integrating the Google Maps API into an HTML application. You include the Google Maps script inside a <script> tag, and there’s also a sibling <p> tag with some text. Now, let’s see how the browser handles this in the default case:

  • For rendering the content in the browser, it begins parsing the HTML.
  • If the browser encounters a <script> tag during parsing, it pauses the HTML parsing and starts downloading the script.
  • This script download process blocks further parsing of the HTML until the script is fully downloaded and executed.
  • As a result, this delay in rendering can negatively affect the user experience, as the page is held up until the script has finished loading and running. This default behavior can cause slower load times and impact the responsiveness of the page.

Async way of loading a script

As we saw in the default case, the HTML parsing process was blocked because the browser had to wait for the script to download and execute, which resulted in slower rendering of the application. However, there’s a better way to handle this. By adding the async attribute to the <script> tag, we can improve this process. When a script is included with the async attribute, it instructs the browser to download the script asynchronously while still parsing the HTML document. This means the script is fetched in the background, without interrupting or blocking the HTML parsing, leading to faster page rendering.

Let’s use a simple analogy to explain async programming

Imagine you’re at a fast-food drive-thru. While your food is being prepared, the drive-thru continues to serve other customers. Once your food is ready, you pick it up and drive off. Everything happens independently and quickly. In programming, async lets tasks run at the same time, without waiting for others to finish. Each task gets done as soon as it’s ready.

Let’s revisit the same example from the default case to better understand this behavior in relation to the code:

<!----============Code============----> 
<p>content before script...</p> 
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=myMap" async></script> 
<p>content after script...</p>
Async behaviour

Async behaviour

Let’s break down what happens when we add the async attribute to the <script> tag in the example above. Here’s how the browser handles this in the asynchronous case:

  • The browser begins parsing the HTML to render the content.
  • When the async attribute is added to a <script> element, the browser downloads the script in parallel with the rest of the page’s content.
  • Once the script finishes downloading, the browser executes it immediately, without waiting for the entire page to finish parsing.
  • This means the script can run at any point during the page load, without blocking the parsing of the HTML.
  • The async attribute is especially useful for scripts that are independent of other scripts and page content, as their loading won’t interrupt the user’s experience.

Note: However, since async scripts do not block parsing and can be executed at any time, there’s no guarantee that they will run in the order they appear in the HTML.

Defer way of loading a script

The defer attribute offers another solution to handle script loading more efficiently. When we use the defer attribute in a <script> tag, it allows the browser to download the script asynchronously while still parsing the HTML document. However, unlike the async attribute, the execution of the script is delayed until the entire HTML document has been fully parsed. This ensures that the script doesn’t block the page’s rendering process, while still executing in the correct order after the HTML content is completely loaded.

Let’s use a simple analogy to explain async programming

Now, imagine a sit-down restaurant where courses are served in order: appetizer first, then main course, and finally dessert. You wait for the right moment before each course arrives. In programming, defer delays tasks until the HTML is fully loaded, ensuring they run in the right order without blocking the page’s rendering.

Let’s revisit the same example from the default case to better understand this behavior in relation to the code:

<!----============Code============----> 
<p>content before script...</p> 
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=myMap" defer></script> 
<p>content after script...</p>
Defer behaviour

Defer behaviour

Let’s break down what happens when we add the defer attribute to the <script> tag in the example above. Here’s how the browser handles this in the deferred case:

  • The browser starts parsing the HTML to render the content.
  • When the defer attribute is included in a <script> tag, the browser is instructed to download the script in the background while it continues parsing the HTML document.
  • The script’s execution is postponed until the entire HTML document has been fully parsed, ensuring that the page content is displayed to the user without waiting for the script to load and execute.

Note: The defer attribute preserves the order of script execution based on their position in the HTML, making it ideal for scripts that depend on one another or require the DOM to be fully parsed before execution. 

When to use Async and when to use Defer?

Async:
We’ll use async attribute method when we want to load scripts concurrently without blocking HTML parsing and rendering.

Let’s consider some scenarios where using async is beneficial:

  • Tracking Scripts or Analytics: Scripts like Google Analytics are often loaded asynchronously. These scripts don’t interact with the DOM and can be delayed without affecting the user experience, making them ideal candidates for async loading.
  • Third-Party Widgets: Social media buttons or comment sections from third-party services can be loaded asynchronously as they don’t depend on the page’s content to function.
  • Independent Modules: For example, a weather widget or news ticker that operates independently of the rest of the page can be loaded with async, ensuring it doesn’t block the rendering of other elements.

Defer:
We’ll use defer attribute method when we want to allow scripts to load asynchronously but ensures they are executed only once the HTML parsing is complete, preventing them from blocking the rendering process.

Let’s consider some scenarios where using defer is beneficial:

  • Scripts that Manipulate the DOM: If a script modifies or interacts with DOM elements, it should only execute once the entire HTML document is fully parsed. Using defer ensures the script runs only after the DOM is ready.
  • Libraries or Frameworks: For libraries like jQuery or frameworks that interact with the DOM extensively, defer is a good choice. It ensures the library or framework is loaded and available for other scripts when needed.
  • Website Initialization Code: Initialization scripts that set up event listeners or perform DOM manipulations should run after the entire HTML document is parsed, which can be achieved by using defer.

Conclusion

Both async and defer allow HTML parsing to continue without waiting for the script to download, improving page load speed. The key difference is when the script executes. With async, the script runs as soon as it’s downloaded, potentially before the HTML is fully parsed. This is ideal for independent scripts that don’t rely on the DOM. In contrast, defer ensures the script runs only after the HTML is completely parsed, but before the DOMContentLoaded event. Use async for scripts that can run independently and defer for scripts that need the DOM or require execution order.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *