defer vs async in JavaScript <script> tag
When you include external JS files in HTML like this:
<script src="script.js"></script>
- By default → JS is loaded and executed immediately, blocking HTML parsing (❌ bad for performance).
- To improve → we use
asyncordefer.
1. async Attribute
- Script is downloaded asynchronously (without blocking HTML parsing).
- Once downloaded, it executes immediately (⚡ even if HTML is not fully parsed).
- Scripts load out of order (depends on which file loads first).
✅ Example:
<script src="analytics.js" async></script>
<script src="main.js" async></script>
👉 If analytics.js loads faster, it executes first, even before main.js.
🔹 Best for:
- Independent scripts (e.g., ads, analytics, trackers) that don’t depend on DOM or other scripts.
2. defer Attribute
- Script is downloaded asynchronously (parallel with HTML parsing).
- But execution is deferred until after HTML is fully parsed.
- Scripts execute in the order they appear in the document.
✅ Example:
<script src="lib.js" defer></script>
<script src="main.js" defer></script>
👉 lib.js loads first → executes before main.js after parsing finishes.
🔹 Best for:
- DOM-related scripts (e.g., manipulating elements, initializing app).
- When script order matters.
🔹 Difference Table
| Feature | async ⚡ |
defer 🕒 |
|---|---|---|
| Downloading | Parallel with HTML parsing | Parallel with HTML parsing |
| Execution timing | Immediately after download | After HTML parsing finishes |
| Execution order | Unpredictable (depends on load time) | Preserves order (top → bottom) |
| Blocks HTML parsing? | No (but execution can pause parsing) | No |
| Use case | Independent scripts (analytics, ads) | DOM-dependent scripts, app logic |
🔹 Visualization
Without async or defer
HTML Parse ---- BLOCKED ----> Continue
JS Download + Execute
With async
HTML Parse + JS Download (parallel)
↓
JS Execute (as soon as ready, may pause parsing)
With defer
HTML Parse + JS Download (parallel)
↓
JS Execute (after parsing completes, in order)
🔹 Quick Example in HTML
<!DOCTYPE html>
<html>
<head>
<script src="analytics.js" async></script> <!-- independent -->
<script src="lib.js" defer></script> <!-- needs DOM -->
<script src="main.js" defer></script> <!-- depends on lib.js -->
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
👉 So in MERN apps, usually:
- Use
deferfor main bundle.js (React app needs DOM ready). - Use
asyncfor external services like Google Analytics, ads, etc.