Sitemap

Javascript: Async and Defer

13 min readDec 7, 2023

JavaScript brings life to webpages, but how we load scripts matters for optimal performance.
We can think of async and defer as two ways JavaScript can load and execute scripts on a webpage without blocking other processes like loading content or rendering the page.

Knfrmd article on async and defer in javasscript

Async

When you add the `async` attribute to a `<script>` element, it allows the browser to download the script in parallel with the loading of the rest of the webpage. As the script finishes downloading, the browser can execute it immediately, without waiting for the entire page to finish parsing. This means the script execution could happen at any time and does not block the page’s parsing process. The `async` attribute is beneficial for scripts that are independent of other scripts and page content since their loading does not disrupt the user’s browsing experience.

However, because `async` scripts do not block parsing and can be executed out of order, they are not guaranteed to run in the order they appear in the HTML. Consequently, `async` is best used for scripts that do not depend on other scripts and do not modify the DOM structure.

If script execution order matters, or a script needs to interact with the fully-parsed DOM, the `defer` attribute should be used instead. Scripts with `defer` are executed in order after the document has been parsed but before firing the `DOMContentLoaded` event, which means they are suitable for scripts that need the full HTML structure to be in place.

Defer

The `defer` attribute is used in HTML to indicate that a `<script>` tag should not block the loading of the page’s content. When you include `defer` in a `<script>` tag, the browser is instructed to download the script in the background while it continues to parse the HTML document. The script execution is deferred until after the HTML document has been fully parsed, ensuring that the page’s content can be displayed to the user without waiting for the script to load and execute. This attribute maintains the order of script execution based on their position in the document, making it useful for scripts that depend on each other and on the complete parsing of the DOM.

Can both be used together?

While both async and defer are useful for non-blocking script loading, they should not be used together on the same script tag.

In HTML, when you use both the `async` and `defer` attributes on a `<script>` tag, the `async` attribute takes precedence over `defer`. If the browser that is loading the page supports `async`, it will ignore `defer` and load the script asynchronously.

Here’s what happens when both attributes are present:

  1. The script will be downloaded in the background, alongside the parsing of the rest of the HTML.
  2. As soon as the script is finished downloading, it will be executed, regardless of whether the HTML document is fully parsed or not.
  3. The `defer` attribute’s instruction to wait until the HTML parsing is complete before executing the script is overridden by `async`.

This behavior reinforces the primary intent of `async`, which is to allow the script to run as soon as it’s available, without waiting for anything else.

Remember that using both `async` and `defer` on a single `<script>` tag is unnecessary and could be confusing.

If you need a script to execute as soon as possible, without regard to the order of execution or the document’s readiness, use `async`.

If you need the script to execute after the HTML has been fully parsed and in order of appearance, use `defer`.

Choose one attribute based on the desired loading and execution behavior required for the script in question.

Press enter or click to view image in full size
image explaining async and defer in javascript

When to use Async and when to use Defer

Let’s imagine a cooking scenario to understand this!

  • Async can be likened to a high-speed convection oven. In a busy kitchen preparing a variety of dishes, the convection oven operates at an accelerated pace, distributing heat evenly and reducing cooking time. Similarly, async in programming handles tasks concurrently, leveraging resources efficiently without waiting for one task to finish before starting another. It operates swiftly, executing processes independently and in parallel, much like the convection oven quickly cooking multiple items simultaneously.
image explaining asynchronous programming
  • Defer, on the other hand, embodies the characteristics of a slow cooker. When preparing a hearty stew or a tender roast, the slow cooker method involves patience and strategic timing. Ingredients are combined, set to cook slowly over an extended period, allowing flavors to meld and intensify.
image explaining defer in javascript

In programming, defer schedules tasks or actions to be executed at a later stage, mirroring the slow cooker's approach of delaying the completion of tasks until specific conditions are met or a particular moment arrives. Just as the slow cooker method waits for the opportune time to complete the dish, defer ensures actions are postponed until the right context or situation arises in the program's execution flow.

Async Examples

Consider a scenario where a website has various analytics and tracking scripts from different providers. These scripts don’t rely on each other or the DOM elements to function.

Tracking Scripts or Analytics

Scripts like Google Analytics can often be loaded asynchronously as they do not typically interact with the DOM and their loading can be delayed without impacting the user experience.

Third-party Widgets

Social media sharing buttons or comment sections provided by third-party services can often be loaded asynchronously since they don’t need to interact with the initial page content.

Independent Modules

If a web page includes a weather widget or a news ticker that operates independently of the rest of the page, loading it using async would not block the rendering of other page elements.

Using async for these scripts would be advantageous. By employing async, these scripts can be loaded concurrently without blocking the parsing and rendering of the HTML content. This ensures that the scripts are fetched in parallel, enhancing the overall loading performance of the webpage.

Defer Examples

Imagine a situation where a script is responsible for manipulating or interacting with DOM elements and requires the entire HTML document to be parsed before execution. For instance, a script that modifies the layout or content based on the document structure

Scripts that Manipulate the DOM

If the JavaScript adds elements to the DOM or depends on the presence of specific elements, using defer ensures that the script will only run once the HTML is fully parsed.

Libraries or Frameworks

If you’re using a library like jQuery or a framework that needs to interact with the DOM extensively and should be available to other scripts, defer is appropriate.

Website Initialization Code

If your webpage has initialization code that sets up event listeners or performs DOM manipulations, defer will ensure that the entire HTML document is available before the script executes.

By using defer, the script can be loaded asynchronously but will wait to execute until the HTML parsing is complete. This ensures that the script doesn't hinder the rendering process and runs only when the DOM is fully available.

Impact on Web Performance

Loading Time

The choice between async and defer can significantly impact the loading time of a webpage. When a script is loaded without any attributes, it defaults to blocking, meaning it will pause HTML parsing and rendering until the script is fetched and executed. In contrast, using async or defer allows the HTML parsing and rendering to continue while fetching the script asynchronously.

Experience

Loading JavaScript asynchronously (async) or deferring its execution (defer) can improve user experience by preventing delays in rendering content. Scripts that are non-essential for initial page display can be loaded asynchronously (async), allowing the page to render faster. Meanwhile, essential scripts requiring full document availability can be deferred (defer), ensuring they execute at the appropriate time without blocking the initial rendering.

Page Rendering

With async, the script is fetched asynchronously and executed immediately when downloaded, potentially causing rendering delays if the script is large or crucial for initial rendering.

defer, on the other hand, ensures that scripts are fetched asynchronously but wait until the HTML parsing is complete before execution, minimizing rendering interruptions.

For developers, it’s essential to analyze the interaction between scripts and the page content to make an informed decision. Profiling tools and site performance audits (like those provided by Google’s Lighthouse) can be of great help to measure the impact of async and defer and optimize the loading process accordingly.

Press enter or click to view image in full size

Loading scripts with async can significantly improve the perceived loading time of a page because it allows the browser to continue parsing and rendering the rest of the page while the script is being fetched and executed. This is particularly useful for scripts that are not essential to the initial rendering of the page, as it prevents them from being a bottleneck in the loading process. However, asynchronous scripts are executed as soon as they are loaded, which means they can potentially interrupt the parsing if they load quickly.

Press enter or click to view image in full size

Using defer postpones script execution until the HTML parser has finished. This means the user will see a fully rendered page without waiting for JavaScript execution, leading to a faster Time to Interactive (TTI). It preserves the order of script execution, mirroring the order they appear in the page's source code. This can prevent issues where scripts depend on each other but are executed out of sequence, which could happen with async.

Press enter or click to view image in full size

By ensuring that scripts run after the document has been fully parsed, defer reduces the likelihood of JavaScript attempting to interact with DOM elements that haven’t been loaded yet.

Choosing the right attribute for your scripts can pleasantly influence the critical rendering path, reducing render-blocking scripts, and enhancing overall user experience. For instance, search engines may prioritize sites with faster loading times, leading to better SEO rankings.

Remember that scripts that are not crucial for initial page rendering could be loaded asynchronously or even postponed until after the page has loaded, perhaps using further lazy loading techniques.

Case Study

In the context of a live chat or chatbot embedded within a web page, the implementation strategy should aim for minimal impact on page load time while ensuring the chat feature becomes available as soon as it’s needed.

Let’s explore a scenario where you could integrate a live chat feature using async or defer.

Live Chat/Chatbot Scenario

Chatbot Integration with Async
Suppose you have an e-commerce website with a customer service chatbot that assists users with their questions while they browse products. Since the chatbot is a separate component that doesn’t modify the DOM structure used to display products, and its operation doesn’t necessarily depend on other scripts, you could load the chatbot’s script asynchronously.

Advantage

The chatbot script can be downloaded in parallel to the page loading without blocking the rendering of the page content. This way, you ensure that visitors can start looking at products immediately, and they will have access to the chatbot as soon as it’s downloaded and ready, without having to wait for the entire page to load.

Implementation Example

<script async src="chatbot.js"></script>

Chatbot Integration with Defer
Alternatively, if the chatbot needs to interact with HTML elements — perhaps to display introductory information in a specific div element, or if there’s a dependency on another script (like jQuery), you might choose to defer the chatbot script.

Advantage

Defer ensures that the script won’t run until after the HTML has been fully parsed. This guarantees that all the necessary elements the chatbot might need are available. It also maintains the sequence of scripts, which is crucial if the chatbot’s functionality relies on any preceding script.

Implementation Example

<script defer src="chatbot.js"></script>

Performance Impact

In both scenarios, the use of async or defer is hinged on the objective of maintaining a high-quality user experience by minimizing disruption to the page's loading performance.

Async
With an async attribute, as the script is loaded in parallel to page loading, there’s a chance that the chatbot might be ready and pop up while the user is still engaging with the initial content. This can be a double-edged sword, as it can either be engaging or distracting, depending on how intrusive the chatbot interface is designed to be.

Defer
By deferring the chatbot’s script, you are postponing its availability but ensuring a smoother loading experience. The chatbot only becomes available after the page has loaded, which might be preferred for users who want to focus on browsing without interruption. However, care must be taken in the script’s placement, as defer still guarantees execution before the DOMContentLoaded event.

User Experience Considerations
It’s worth noting that beyond the technical integration, the user experience should be carefully considered. For instance, you might want to ensure that the chatbot does not cover essential information on the site and is easily dismissible. Also, the timing of its appearance should be reasonable; if the chatbot pops up too early, it might distract from the browsing experience, but if it appears too late, users might not notice it when they need assistance.

Through real-world testing and performance measurement tools, developers and site owners can evaluate the impact of both async and defer in the context of their specific use case, and choose the option that offers the best balance between functionality and performance.

The defer attribute, when used on <script> elements, has specific effects on the execution order of JavaScript files, which are essential to understand for maintaining script dependencies:

Order Maintenance

When multiple scripts are included with the defer attribute, their execution order is guaranteed to be the same as the order in which they appear in the document. This is unlike scripts loaded with the async attribute, which are executed as soon as they are downloaded, without any guarantee of order.

For example, consider the following HTML snippet:

<script defer src="library.js"></script> <script defer src="app.js"></script>

In this case, library.js contains a JavaScript library that app.js relies on. Because both scripts are loaded with defer, the browser will guarantee the following:

Downloading

Both library.js and app.js can be downloaded in parallel, without blocking the HTML parser. This improves page load time because the browser is not idle while fetching scripts.

Parsing

While the scripts are being downloaded, the browser continues to parse the HTML and construct the DOM.

Execution Order

The scripts will not execute until the HTML document has been fully parsed. library.js will execute before app.js, because it comes first in the document order. This is crucial for app.js since it depends on the library being loaded.

Execution Timing

The scripts are executed before the DOMContentLoaded event is fired. This event signifies that all of the HTML has been completely parsed, the DOM tree is built, and all deferred scripts have been executed.

The maintenance of execution order is vital for scripts that have dependencies on each other. If a script depends on a library or another script, using defer ensures that the dependent script does not execute before its dependency is ready. This prevents errors that would occur if a script tried to call a function or use a feature of a library that hadn't yet been loaded.

Execution After Parsing

The fact that deferred scripts execute after the document has been parsed means that when the scripts run, they can interact with a fully constructed DOM. This is particularly useful for scripts that need to manipulate or initialize elements on the page because by the time the script runs, those elements are guaranteed to be available.

This behavior is different from scripts without defer or async, which would block the HTML parser as soon as they begin to load. Such blocking behavior can lead to increased render times and a slower user experience.

Using defer is a safeguard for maintaining script execution order and ensuring a script's interaction with the document only after it has been fully parsed, which is critical for script dependencies and DOM manipulation. It's a beneficial practice in web development that allows you to structure your code in a clear, predictable manner while optimizing for performance.

Conclusion

Mastering the art of JavaScript loading with Async and Defer is like orchestrating a symphony in the digital world.

Picture your website as a stage, where scripts, like talented performers, bring it to life. Understanding when to let Async take the spotlight for immediate action and when to cue Defer for a synchronized execution ensures a harmonious performance.

Just as a conductor orchestrates music, balancing the tempo and harmony, employing these attributes separately offers your website the rhythm it needs for flawless user experience.

So, remember, whether it’s the instant rush of Async or the well-timed Defer, conducting your scripts wisely creates a web experience that captivates and delights your audience.

In the digital kitchen of web development, choosing between ‘async’ and ‘defer’ attributes when loading JavaScript is akin to a chef selecting the ideal cooking technique for a particular recipe.

  • Use ‘async’ to serve up scripts like side dishes that are ready at their own pace, such as tracking scripts or independent widgets that do not depend on other parts of the page. This allows these scripts to load without delaying the main content, improving site responsiveness and user engagement without sacrificing functionality.
  • Opt for ‘defer’ when preparing the main course, ensuring that all ingredients (DOM elements) are in place before the script, which could be a foundational JavaScript library or critical initialization code, begins its work. ‘Defer’ guarantees the script will execute only after the HTML is fully parsed, maintaining execution order and offering a smooth and structured page loading experience.

Carefully selecting ‘async’ or ‘defer’ when loading scripts ensures maximum performance and a harmonious user experience — just as choosing the right cooking method brings out the best in each dish and creates an unforgettable dining experience.

https://www.knfrmd.com/posts/web-performance/async-and-defer

--

--

Knfrmd
Knfrmd

Written by Knfrmd

A web design, development, and marketing automation agency whose mission is to reduce the user frustration while interacting with the web .

No responses yet