Async vs Defer - Network Optimisation for Web Apps

Preeti RoshanPreeti Roshan
3 min read

There are mainly 4 ways in which we can add scripts to our HTML webpage. Let's discuss these in detail in the following blog. Along with these, we'll also be having a quick look over handling scripts pointing to JS modules.

Let's begin!

1. In the head tag:

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./script1.js"></script>
</head>

Here, HTML parsing starts, but as soon as the script tag is encountered, the HTML parsing is blocked until the browser downloads the script and executes it.

2. After the body tag:

<body>
  Body
</body>
<script src="./script2.js"></script>

In this case, the HTML parsing is done and the DOM tree is created first, after which the browser encounters the script tag. Here, HTML parsing is not blocked but still, the process does take time.

To avoid that, we can download the script in parallel with the HTML parsing to speed up the process. The next two methods help us do just that:

3. Using async attribute :

As the name suggests, this involves asynchronous handling of the script.

Here, as soon as the browser reaches the script tag, it starts downloading the script asynchronously, while continuing with the HTML parsing.

Once the script is downloaded, the HTML parsing is blocked until the script is executed.

After the script execution is complete, the HTML parsing is continued.

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script async src="./script1.js"></script>
</head>

This does provide us some improvement as parsing is not blocked while the script is being downloaded, but is there any way we can avoid blocking the HTML parsing even during script execution? Yes.

4. Using defer attribute

This allows the script to be downloaded in parallel with HTML parsing. But the script is executed only after the HTML parsing is complete and before the DOMContentLoaded event is fired.

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script defer src="./script1.js"></script>
</head>

Loading JS Asynchronously In case of Modules

What are Modules?

A module is a piece of code/JS that exports some functions, variables, etc. which can be used by other modules. For eg, below is an example of a simple JS module exporting the calculateFactorialSum function.

import { getFactorial } from './getFactorial';
export const calculateFactorialSum = (a, b) => { const sum = a+b getFactorial(sum) }

Defer

In the case of scripts pointing to JS modules, the default behavior is of defer type only. This means that all the necessary JS (i.e., the module with all its dependencies) is loaded in parallel with the HTML parsing and executed once the HTML parsing is done.

Since defer is the default behavior, we don't need to specify it explicitly.

<script type="module" src="./script2.js"></script>

Async

We can also use the async attribute for modules. In this case, the required JS is fetched in parallel to HTML parsing. Once the JS is loaded, HTML parsing is blocked until its execution is completed.

<script async type="module" src="./script2.js"></script>

This is all for this blog. Hope it helps you. In the next blog, we'll be discussing a few more network optimization techniques in depth.

Thanks for reading :)

0
Subscribe to my newsletter

Read articles from Preeti Roshan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Preeti Roshan
Preeti Roshan

Talks about Javascript and ReactJs