How JavaScript's Async and Defer Tags Let You Load Pages Faster

JavaScript has a huge impact on web page performance, but much of this impact comes long before the script even runs. When a browser normally encounters a JavaScript block, it stops rendering the page in order to download and run the script. Where 38% of visitors will leave a website after waiting just 5 seconds for it to load, waiting on JavaScript simply isn't a viable option.

Fortunately, this doesn't have to be the case. The async and defer HTML attributes let you control when and how JavaScript files are downloaded and executed. Using these attributes, you can reduce the amount of time users spend waiting on JavaScript without having to change your scripts.

What Are Async and Defer?

async and defer are <script> attributes that determine how JavaScript files and blocks are processed. Normally when a browser encounters a <script> block, it stops parsing the page's HTML while it downloads and runs the script. It only continues parsing once the script has finished. Depending on the number and size of the page's scripts, this can significantly increase the page load time.

Normal (Synchronous) Execution:

Diagram of synchronous JavaScript execution

async and defer mitigate this by downloading scripts alongside the parser, reducing the overall impact on page load times. Both tags perform similar functions, but they work in somewhat different ways.

Async

With async, external JavaScript files are downloaded asynchronously, allowing the parser to continue rendering the page. As soon as the download is finished, the browser runs the script. Although running the script still interrupts the parser, the time needed to download the script is essentially removed from the page download time.

Asynchronous Execution:

Diagram of asynchronous JavaScript execution

The main benefit of async is that it lets you download scripts without interrupting the parser. However, scripts run as soon as they're finished downloading, meaning one script may run before another script even if the latter script was defined first in the page's HTML. This also means scripts could run before the browser has finished building the Document Object Model (DOM). async benefits scripts that don't rely on other scripts or the complete DOM in order to successfully run.

Defer

Like async, defer downloads script files alongside the parser. The difference is that defer holds off on executing scripts until after the parser is finished. defer also executes scripts in the order in which they are defined, allowing you to run scripts that depend on other scripts.

Deferred Execution:

Diagram of deferred JavaScript execution

defer only works for scripts with a src attribute. However, it guarantees that your scripts will only run after the DOM is complete, and in the order that they appear in the page's HTML.

Performance Benefits

Tests performed on the Google Maps API showed that using async significantly reduced the time needed to display a map element to the user. With neither attribute enabled, it took 658 milliseconds to fire the DOMContentLoaded event, and 700—1000ms before the user could start customizing the map.

With async enabled, it took only 35ms to fire the DOMContentLoaded event and 300—500ms before the user could start customizing the map. In this test, both async and defer were defined in the script block. Modern browsers default to using async, whereas older browsers that don't support async fall back to defer.

When Should I Use One Over the Other?

In general, defer offers more benefits over async including preserved execution order, no parser blocking, and access to the page's complete DOM. In addition, defer works reliably when combined with synchronous and async scripts. All modern browsers (with the exception of Opera Mini) support defer as well as async.

Use async if your script...

Use defer if your script...

  • Has no other dependencies
  • Is not used alongside synchronous scripts
  • Does not require a fully parsed DOM
  • Depends on other scripts
  • Is used alongside synchronous scripts
  • Requires a fully parsed DOM