Why a script can slow down page construction
As a browser reads an HTML document, it builds a representation of the page called the DOM. When the parser encounters a conventional external script, such as <script src="app.js"></script>, it normally pauses parsing until the script has downloaded and executed. That pause matters because JavaScript can change the document, including content that comes after the script tag.
The async and defer attributes let the browser download an external classic script while it continues parsing HTML. They do not make the script free: downloading, parsing and executing JavaScript still use resources. Their main advantage is that the browser need not stop building the DOM just to wait for the file to arrive.
Script loading is only one part of rendering performance. A large script can still occupy the main thread when it runs, delaying user interaction or visible updates. Use async or defer to remove an avoidable parsing pause, then consider whether the page needs all that JavaScript in the first place.
Async: run when the file is ready
An async script looks like <script async src="analytics.js"></script>. The browser can fetch the file while parsing continues. Once the download is ready, parsing may pause so the script can execute. If several async scripts are present, their execution order depends on when they become ready, not on the order of their tags in the HTML.
Async is a good fit for a self-contained script that does not depend on another script and does not need the full DOM. For example, a small measurement script that initializes itself without reading page elements may be suitable. A script that expects a particular button to exist is less predictable: it might execute before the parser reaches that button.
An async script also does not hold up the DOMContentLoaded event, which signals that the initial HTML has been parsed. Depending on timing, an async script may run before or after that event. If it must work with page elements, it needs a reliable readiness check or an initialization method that does not assume those elements already exist.
Defer: wait until parsing is complete
A deferred script looks like <script defer src="app.js"></script>. Its file can download while the browser parses HTML, but it executes after parsing finishes. This makes defer useful for code that needs to find elements throughout the page without interrupting construction of the DOM as soon as the download completes.
Deferred external classic scripts execute in document order. If helpers.js appears before app.js and both use defer, app.js can rely on helpers.js having executed first. The browser waits for deferred scripts to finish before firing DOMContentLoaded, so that event is a useful point for other code to know the deferred setup has run.
Defer does not mean “run after the page is visible” or “run in the background.” Execution still takes time on the main thread, and a slow deferred script can delay DOMContentLoaded. It is best understood as a choice about when the script runs relative to HTML parsing, not as a guarantee that the page will feel fast.
Choosing an attribute for common page scripts
For a page interface script that attaches event listeners, reads elements or depends on another file, start by considering defer. Put dependent deferred scripts in the required order in the HTML. For an independent script whose timing does not matter to the page, consider async. Avoid using async for a chain of files that must execute in a particular order.
Keep the distinction between external classic scripts and other forms of JavaScript in mind. Async and defer are intended for scripts with a src attribute; adding them to an inline classic script does not give that inline code the same loading behavior. Module scripts use deferred-style behavior by default, so a module often needs no defer attribute. An async module, however, runs when it is ready rather than waiting for parsing to finish.
You can also place a conventional script near the end of the body so most HTML has already been parsed when execution begins. That may be adequate for a small page, but it still pauses the parser at that point. Defer makes the intended timing explicit and allows the download to begin when the browser encounters the tag.
Verify the result on a real page
Start with a simple inventory: note which scripts change the page, which depend on other scripts and which can run independently. Choose defer for DOM-dependent or ordered classic scripts and async for independent ones. Then test that page elements initialize correctly and that no script assumes a dependency has loaded merely because its tag appears earlier.
Use browser developer tools to inspect when files download, when scripts execute and whether long tasks delay interaction. If a page remains sluggish after changing script attributes, reduce or postpone unnecessary work rather than adding more loading flags. The goal is not to make every script async; it is to give each script a loading strategy that matches what it actually needs.



