
Both async
and defer
attributes are used to fetch scripts asynchronously without blocking the HTML parser, but what is the difference between them? And when to use each.
About async and defer
- Both require the
src
attribute and only work for external scripts. async
overridesdefer
if both exist on the same script.- Scripts with
type="module"
are deferred by default. - Scripts created by
document.createElement('script')
are async by default. async
anddefer
are ignored in inline scripts with nosrc
.
Scripts with no defer / async
To better understand the difference between async
and defer
, let’s first examine what happens when we don’t set any of them.
- The browser fetches the HTML.
- It starts parsing the HTML to form the DOM.
- It finds the script element.
- The parser is blocked until the script is loaded and executed.
This means the script doesn’t know about the elements under it, therefore it can’t interact with them.
Additionally, loading large scripts at the top of your HTML can slow down your website resulting in a blank screen.
A simple and ineffective solution is placing the script at the bottom of the page.
Scripts with async
When adding the async
attribute to a script element, the same process is followed as before. But this time, the script loads on a separate thread in parallel to parsing HTML, and once the fetching is done, its execution blocks the parser.
The execution order of multiple async scripts is not guaranteed, as each script will execute as soon as it is fetched.
Scripts with defer
Similar to async, deferred scripts will load in the background without blocking the parsing process, but they will only execute after the parsing is done.
This means deferred scripts won’t block the HTML parser and can interact with other elements even if they come after the script.
<script defer src="script.js"></script>
<p class="name"></p> <!-- the script can access this paragraph -->
Also, deferred scripts will execute in the order they are declared in.
When to use defer vs async?
- Use just
<script>
for small inline scripts to set global settings. - Use
async
for independent scripts like analytics. - Use
defer
for scripts that manipulate the DOM or depend on other scripts.