Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Control when external scripts download and execute relative to HTML parsing. Three strategies for balancing page load speed with script execution order.
By default, when the browser encounters a <script> tag, it stops parsing HTML, downloads the script, executes it, and only then resumes parsing. For large scripts, this creates a visible delay before the page renders. The async and defer attributes change this behavior by allowing the download to happen in parallel with parsing.
Applies to: <script> with a src attribute (external scripts only). These attributes have no effect on inline scripts.
| Strategy | Downloads | Executes | Execution Order |
|---|---|---|---|
| (none) | Blocks parsing during download | Immediately after download | In document order |
async | In parallel with parsing | As soon as download finishes (pauses parser) | Not guaranteed |
defer | In parallel with parsing | After HTML is fully parsed, before DOMContentLoaded | In document order |
type="module" | In parallel with parsing (deferred by default) | After HTML is fully parsed | In document order |
The parser stops at each script tag, fetches the file, executes it, then continues. This guarantees execution order but delays rendering.
<!-- Normal (no attribute): blocks HTML parsing --><!-- Parser stops, downloads script, executes it, then resumes parsing --><script src="/js/blocking.js"></script>
The script downloads in the background while parsing continues. As soon as the script finishes downloading, the parser pauses to execute it. If multiple async scripts are present, they execute in whichever order they finish downloading, not document order.
<!-- async: downloads in parallel, executes as soon as ready --><!-- Execution order is NOT guaranteed between multiple async scripts --><script src="/js/analytics.js" async></script><script src="/js/ads.js" async></script>
Best for: Independent scripts that do not depend on other scripts or DOM state — analytics, ad tags, monitoring, A/B testing.
The script downloads in the background like async, but execution is postponed until HTML parsing is complete. Multiple deferred scripts execute in the order they appear in the document, and all run before the DOMContentLoaded event fires.
<!-- defer: downloads in parallel, executes after parsing in document order --><!-- Guaranteed to execute in the order they appear --><script src="/js/framework.js" defer></script><script src="/js/app.js" defer></script>
Best for: Application scripts that need the full DOM and depend on each other's execution order — frameworks, UI code, form handlers.
ES module scripts are deferred by default without needing the defer attribute. They also support top-level await, strict mode is always on, and each module has its own scope (no global variable pollution).
Adding async to a module script makes it execute as soon as it and its dependencies are ready, similar to async on classic scripts.
<!-- type="module" scripts are deferred by default --><script type="module" src="/js/app.js"></script> <!-- You can add async to a module to make it execute as soon as ready --><script type="module" src="/js/analytics.js" async></script> <!-- Modules support top-level await --><script type="module"> const data = await fetch('/api/config').then(r => r.json()); console.log(data);</script>
| Scenario | Use | Reason |
|---|---|---|
| Analytics, ads, third-party widgets | async | Independent; order does not matter; should not delay page |
| App scripts, UI initialization | defer | Needs the DOM; depends on load order |
| Framework/library followed by app code | defer (both) | Guarantees library loads before app code |
| Modern ES modules | type="module" | Deferred by default; supports import/export |
| Script that must run before any rendering | (none) | Rare; only for critical inline polyfills or theme detection |
<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" /> <title>Loading Strategy Example</title> <!-- Critical CSS: render-blocking (intentional) --> <link rel="stylesheet" href="/css/main.css" /> <!-- Framework: defer ensures it runs before app.js, after parsing --> <script src="/js/framework.js" defer></script> <script src="/js/app.js" defer></script> <!-- Analytics: independent, order does not matter --> <script src="/js/analytics.js" async></script></head><body> <h1>Content is visible before scripts execute</h1></body></html>
src attribute. Inline scripts always execute immediately (except type="module" inline scripts, which are deferred).DOMContentLoaded event. A slow deferred script holds up any code waiting for that event.async and defer are present, async takes precedence in browsers that support it. defer acts as a fallback for very old browsers.document.createElement('script') are async by default. Set script.async = false to preserve insertion order.