Why this is asked
This question delves into critical browser runtime behavior and performance optimization. It assesses a candidate's ability to minimize render-blocking resources, improve perceived page load speed, and understand the intricate dance between HTML parsing, script downloading, and execution. Mismanaging script loading can significantly degrade user experience, making this a frequent interview topic.
By default, <script src="..."></script> elements are "parser-blocking." The browser stops parsing HTML, fetches the script, executes it, and then resumes HTML parsing. This can severely delay page rendering. The async and defer attributes modify this behavior:
async: The script is fetched asynchronously in parallel with HTML parsing. As soon as it's downloaded, HTML parsing is paused, the script executes, and then parsing resumes. Execution order amongasyncscripts is not guaranteed.defer: The script is fetched asynchronously in parallel with HTML parsing, but its execution is deferred until the HTML document has been fully parsed. Deferred scripts execute in the order they appear in the document, just before theDOMContentLoadedevent.
<!DOCTYPE html>
<html>
<head>
<title>Script Loading</title>
<!-- Blocks HTML parsing, download, then execute -->
<script src="blocking.js"></script>
<!-- Downloads in parallel, executes when ready (may block parsing) -->
<script async src="async-script.js"></script>
<!-- Downloads in parallel, executes after HTML parsing, in order -->
<script defer src="defer-script-1.js"></script>
<script defer src="defer-script-2.js"></script>
</head>
<body>
<h1>Hello</h1>
<p>Page content.</p>
</body>
</html>
Gotchas: async scripts can execute before the DOM is fully constructed, potentially leading to errors if they try to manipulate elements that don't exist yet. defer ensures DOM availability but still doesn't guarantee when other non-deferred resources (like images) will be loaded. For module scripts (<script type="module">), defer is the default behavior, and async can still be used to override it. Older IE versions had buggy defer implementations.
References: MDN Web Docs: script defer, MDN Web Docs: script async, HTML Living Standard: Scripting
