In the world of web development, optimizing page load times is crucial. Two powerful attributes of the <script>
tag – async
and defer
– can significantly impact your website's performance. Using these attributes without thoroughly understanding them can affect performance and lead to bugs. Let's start from the basics and learn what these attributes do and when to use them.
The Basics: How Scripts Load
By default, when a browser encounters a <script>
tag, it:
- Pauses HTML parsing
- Downloads the script
- Executes the script
- Resumes HTML parsing
This process can slow down page rendering, especially for large scripts or slow connections. Additionally, it can lead to bugs if the script runs before certain HTML elements are fully loaded, which often happens if the script is not placed correctly in the document.
Async and Defer: A Double-Edged Sword
Async
<script async src="script.js"></script>
- What it does: Downloads the script asynchronously while HTML parsing continues.
- When it executes: As soon as it's downloaded, pausing HTML parsing.
- When it is used: Independent scripts that don't rely on other scripts or DOM content.
- Caveat: Can execute out of order, potentially breaking dependencies.
Defer
<script defer src="script.js"></script>
- What it does: Downloads the script while HTML parsing continues.
-
When it executes: After HTML parsing is complete, but before the
DOMContentLoaded
event. - When it is used: Scripts that rely on DOM content or need to execute in a specific order.
- Caveat: May delay execution of critical functionality.
Comparing Behaviors
Attribute | Download | Execution | HTML Parsing | Main Risk |
---|---|---|---|---|
None | Blocks | Immediate | Paused | Slow Initial Render |
Async | Parallel | ASAP | Paused when downloaded | Race Conditions |
Defer | Parallel | After HTML | Continues | Delayed Functionality |
Order of Execution: Async, Defer, and Both
Understanding the order of execution for scripts with different attributes is crucial for managing dependencies and ensuring proper functionality. Here's how it works:
-
Regular scripts (no async or defer):
- Execute in the order they appear in the document.
- Block HTML parsing until they're downloaded and executed.
-
Async scripts:
- Download in parallel and execute as soon as they're available.
- No guaranteed order of execution; they run as soon as they're downloaded.
- May execute before the DOM is fully loaded.
-
Defer scripts:
- Download in parallel but execute only after HTML parsing is complete.
- Execute in the order they appear in the document.
- Run before the
DOMContentLoaded
event.
-
Scripts with both async and defer:
- The
async
attribute takes precedence in modern browsers. - In older browsers that don't support
async
, they fall back todefer
behavior.
- The
Example Execution Order:
<script src="1.js"></script>
<script async src="2.js"></script>
<script async src="3.js"></script>
<script defer src="4.js"></script>
<script defer src="5.js"></script>
Possible execution order:
-
1.js
(blocks parsing) -
3.js
or2.js
(whichever downloads first) -
2.js
or3.js
(whichever downloads second) 4.js
5.js
Note that 2
and 3
could execute in any order or even before 1
if 1.js
takes longer to download.
Best Practices
- Use
async
for independent scripts like analytics. - Use
defer
for scripts that depend on DOM or other scripts. - Place scripts in the
<head>
withasync
ordefer
to start downloading early. - For critical scripts, consider inline scripts in the
<head>
.
Browser Support
Both async
and defer
are widely supported in modern browsers. For older browsers, consider using a script loader or placing scripts at the end of the <body>
.
Top comments (2)
Well written, concise and to the point. Thanks for sharing!
This is really useful, sometimes we use things without understanding them. Thanks for highlighting this.