JavaScript’s defer and async attribute application details

JavaScript scripts are introduced into a large number of web pages, which are usually larger and heavier than HTML, and therefore take longer to process. When the browser encounters a  <script>...</script> tag while loading HTML, the browser cannot continue building the DOM and must wait for the JavaScript script to finish executing. The same is true for external scripts  <script src="..."></script> : the browser must wait for the script to download and complete its execution before continuing to process the rest of the page.

This leads to two important problems:

  1. Scripts cannot access DOM elements below them, scripts cannot add handlers to them, etc.
  2. If there is a clunky script at the top of the page, it “blocks the page”. The user cannot see the content of the page until the script is downloaded and executed.

A common practice is to place the JavaScript script at the end of the page so that it can access the elements above it without blocking the page’s display content. But this solution is far from perfect. For example, the browser won’t notice the script (and can start downloading it) until the full HTML document has been downloaded. For long HTML documents, this can cause significant delays.

That’s not a big deal for people using high-speed connections, who won’t experience this lag. But there are still many parts of the world where people use slow networks, especially mobile networks in some areas.

Fortunately, there are defer and  asynctwo  <script> features that can solve this problem.

defer feature

defer The attribute tells the browser not to wait for the script, the browser will continue processing the HTML, building the DOM. JavaScript scripts are downloaded “in the background” and then executed when the DOM is built.

<!doctype html>
<p>...content before script...</p>

<script defer src=""></script>

<!-- The following is immediately visible -->
<p>...The defer application example...</p>

in other words:

  • defer Scripts with  features do not block the page.
  • Scripts with  defer properties always wait until the DOM has been parsed, but are  DOMContentLoaded executed before events.

The following example will explain what the second sentence means:

<p>...content before scripts...</p>

  document.addEventListener('DOMContentLoaded', () => alert("DOM ready after defer!"));

<script defer src=""></script>

<p>...The contents of the script are immediately displayed...</p>
  1. The page content is displayed immediately.
  2. DOMContentLoaded The event handler waits for  defer the script with the attribute to finish executing. It will only be triggered after the script is downloaded and its execution has ended.

Scripts with  defer attributes maintain their relative order, just like regular scripts.

Suppose, we have two  defer scripts with characteristics: test1.js before and test2.js after.

<script defer src=""></script>
<script defer src=""></script>

The browser scans the page for scripts and downloads them in parallel to improve performance. So in the example above, the two scripts are downloaded in parallel. test2.js may be downloaded first.

However, in defer addition to telling the browser “don’t block the page”, features also ensure the relative order of script execution. Even if  test2.js it is loaded first, it  test1.js will not be executed until the end of execution.

This can be useful when we need to load a JavaScript library before loading scripts that depend on it.

Note: defer Features are only available for external scripts . If  the <script> script doesn’t  src, the attribute is ignored  defer and has no effect for inline scripts.

async feature

async Features are  defer somewhat similar. It also enables scripts not to block the page. However, there are important differences in behavior.

async Features mean that scripts are completely self-contained:

  • Browsers don’t  async block with scripts (and  defer similar).
  • Other scripts don’t wait for  async scripts to load to finish, and similarly, async scripts don’t wait for other scripts.
  • DOMContentLoaded and async scripts don’t wait for each other:
    • DOMContentLoaded May happen before the async script (if the async script doesn’t load until the page is done)
    • DOMContentLoaded Can also happen after an async script (if the async script is short, or loaded from the HTTP cache)

In other words, the async script loads in the background and runs when it is ready. The DOM and other scripts don’t wait for them, and they don’t wait for anything else. async A script is a completely separate script that is executed when the load is complete.

async will not execute in script order, whoever loads first will execute it first.

Loading asynchronously is great when we’re integrating independent third-party scripts into the page: counters, ads, etc., because they don’t depend on our script, and our script shouldn’t wait for them:

<!-- Google Analytics Scripts are typically embedded in pages like this -->
<script async src=""></script>


async and  defer have one thing in common: loading such a script will not block the rendering of the page. Therefore, users can immediately read and understand the page content.

However, there are also some essential differences between them:

asyncLoad priority order . The order of scripts in the document does not matter – the ones loaded first are executed firstirrelevant. Possibly loaded and executed before the document is loaded. This can happen if the script is small or from a cache and the document is long enough.
deferDocument order (their order in the document)Executed after the document has been loaded and parsed (and waited if needed), i.e.  DOMContentLoaded before.

In actual development, defer used for scripts that require the entire DOM, and/or when the relative execution order of scripts is important.

async For stand-alone scripts, such as counters or advertisements, where the relative execution order of these scripts does not matter.

Leave a Comment