Question
You have two external JavaScript files near the end of the <body>: jQuery loaded from a CDN, followed by a local script that depends on jQuery.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="/js/app.js"></script>
What are the performance and behavior differences between leaving these scripts at the bottom of the page and moving them into the <head> with async or defer?
In particular:
- Is adding
asyncto scripts at the end of<body>useful? - Do scripts in
<head>begin downloading while the page is being parsed? - Does
<script defer src="..."></script>in<head>behave like placing scripts before</body>? - If two scripts use
async, can they download concurrently, and does their execution order become unreliable? - What should be used when the second script depends on the first?
- How should older browsers be considered?
Short Answer
By the end of this page, you will understand when browsers download and run external scripts, how async and defer affect HTML parsing, and why dependent files such as jQuery and an application script should usually use defer rather than async.
Concept
A normal external <script> affects the browser in two separate ways:
- Downloading: fetching the JavaScript file from a server.
- Executing: running the JavaScript code.
Without attributes, a classic script blocks HTML parsing when the parser reaches it. The browser normally downloads the script, executes it, and only then continues reading the HTML below it.
<script src="/js/app.js"></script>
The async and defer attributes allow a browser to download an external script while it continues parsing the HTML. Their crucial difference is when the downloaded script executes and whether source order is preserved.
async: execute as soon as each file finishes downloading. Order is not guaranteed.defer: execute after HTML parsing finishes. Deferred classic scripts execute in document order.
This matters because many applications have dependencies. If app.js calls jQuery's $, jQuery must execute first. async is unsafe for that pair because app.js could finish downloading and run before jQuery.
These attributes are not something to postpone until "HTML5 browsers" are available. They are established browser features, and modern browser support is broad. However, test any browser versions your audience must support. Older browsers may ignore unsupported attributes, which can change the fallback behavior.
Mental Model
Imagine the HTML parser is a reader moving through a recipe book, and each script is a task the reader must perform.
- A normal script says: “Stop reading, collect the ingredient, use it now, then continue.”
- An async script says: “Ask someone to fetch the ingredient while reading continues. The instant it arrives, stop and use it.” The ingredients may arrive in any order.
- A defer script says: “Ask someone to fetch the ingredient while reading continues. After the entire recipe has been read, use the ingredients in the listed order.”
For files with dependencies, defer is like following numbered recipe steps. async is suitable only when each task is independent.
Syntax and Examples
A normal script blocks parsing at the point where it appears:
<script src="/js/app.js"></script>
Use defer for scripts that need a predictable order or need the document to be fully parsed:
<head>
<script defer src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script defer src="/js/app.js"></script>
</head>
The browser can fetch both files while it parses the page. Once parsing is complete, it runs jQuery first and then app.js.
// app.js
$(function () {
console.log("jQuery is available and the DOM is ready.");
});
Use async only for an independent script:
<script async src="https://example.com/analytics.js"></script>
For example, analytics code often records page visits and does not provide functions that your application code immediately depends on. It can run whenever its download completes.
For classic external scripts,
asyncanddeferonly have their special loading behavior whensrcis present. If both attributes are present,asynctakes precedence.
Step by Step Execution
Consider a page with two dependent scripts in the document <head>:
<head>
<script defer src="/js/library.js"></script>
<script defer src="/js/app.js"></script>
</head>
<body>
<h1>Account</h1>
</body>
// library.js
window.formatName = function (name) {
return name.toUpperCase();
};
// app.js
console.log(formatName("Ada"));
Execution sequence:
- The browser starts parsing the
<head>. - It discovers
library.jsand starts downloading it without pausing HTML parsing. - It discovers
app.jsand can also start downloading it. - The browser continues parsing the
<body>and creates the<h1>element. - After HTML parsing has completed, the browser executes
library.js. - It then executes
app.js, even ifapp.jshappened to download first. - The console prints
ADA.
Now replace defer with async:
<script async src="/js/library.js"></script>
<script async src="/js/app.js"></script>
Both downloads may overlap, but whichever completes first executes first. If app.js executes before library.js, formatName does not exist yet and the code fails.
Real World Use Cases
- Application bundles with dependencies: Load a vendor bundle before an application bundle using
deferso execution remains ordered. - Page-specific user interface code: Defer code that attaches click handlers or reads page elements, because the HTML will be parsed before it runs.
- Analytics and measurement: Use
asyncwhen a third-party script is independent of your app's startup code. - Advertisements and widgets: Independent third-party integrations often use
async, although their impact on performance and privacy should still be evaluated. - Static sites: Put deferred site JavaScript in
<head>so downloads can start early while the browser builds the page. - Legacy jQuery sites: Load jQuery first and a script that uses
$second withdefer, or retain normal scripts near the end of<body>. Do not mark both asasync.
Real Codebase Usage
In a real project, developers choose a loading strategy based on dependencies and when code is needed.
Ordered application scripts
<head>
<script defer src="/assets/vendor.js"></script>
<script defer src="/assets/app.js"></script>
</head>
This is common when app.js depends on code in vendor.js.
Independent third-party script
<script async src="https://metrics.example.com/tracker.js"></script>
Do not write application startup code that assumes this script has loaded immediately. If an integration requires a callback or event, use the provider's documented loading API.
DOM initialization after deferred code
Deferred scripts run after document parsing, so they can usually select elements directly:
const saveButton = document.querySelector("#save-button");
if (saveButton) {
saveButton.addEventListener("click", saveProfile);
}
The if is a guard clause: it lets the same script work on pages that do not contain that button.
Modern module scripts
For new applications, module scripts are often used:
<script type="module" src="/js/app.js"></script>
Module scripts are deferred by default. Their imports describe dependencies explicitly, which is usually more maintainable than manually ordering many classic script tags.
Common Mistakes
Marking dependent files as async
Broken example:
<script async src="/js/jquery.js"></script>
<script async src="/js/app.js"></script>
// app.js
$("#menu").show();
app.js may run before jQuery is available. Use defer in source order instead:
<script defer src="/js/jquery.js"></script>
<script defer src="/js/app.js"></script>
Assuming async means “runs after the page loads”
It does not. An async script runs as soon as it is ready, possibly before the HTML parser reaches elements later in the page. Do not rely on DOM elements being present unless your code waits for them or the script is deferred.
Assuming defer and bottom-of-body scripts are identical
They are similar in that both avoid blocking most visible HTML parsing. But they are not identical:
- Deferred scripts in
<head>can be discovered and downloaded earlier. - Deferred scripts execute after the document has finished parsing.
- Normal scripts near
</body>still block parsing when the browser reaches them.
Using defer on an inline classic script
<script defer>
console.log("This does not become deferred in the same useful way.");
</script>
Use defer with an external src script. Place inline initialization after the deferred external script only when you know the required code has executed, or keep the initialization in the deferred external file.
Adding both async and defer expecting both benefits
<script async defer src="/js/app.js"></script>
For classic scripts, treat this as async: execution order is not guaranteed. Choose the one that matches your requirements.
Forgetting cache and network effects
async and defer improve how downloading overlaps with parsing, but they do not guarantee a faster page in every measurement. File size, caching, server speed, and third-party scripts still matter.
Comparisons
| Script form | Download timing | Execution timing | Preserves source order? | Good for |
|---|---|---|---|---|
<script src="..."> | When parser reaches it | Immediately after download | Yes | Small scripts needed at that exact point |
Normal script near </body> | Late in parsing | Immediately after download | Yes | Older patterns; simple dependent scripts |
<script defer src="..."> | During HTML parsing | After parsing completes | Yes, among deferred classic scripts | Application code and dependent files |
<script async src="..."> | During HTML parsing | As soon as each download completes | No | Independent analytics or widgets |
<script type="module" src="..."> | During HTML parsing | Deferred by default | Imports manage dependencies | Modern JavaScript applications |
For the jQuery-plus-application scenario:
| Approach | Safe dependency order? | Can start downloads early? |
|---|---|---|
Two normal scripts before </body> | Yes | Usually later |
Two async scripts | No | Yes |
Two defer scripts in <head> | Yes | Yes |
Cheat Sheet
<!-- Normal: parser blocks here -->
<script src="/js/app.js"></script>
<!-- Ordered, runs after HTML parsing -->
<script defer src="/js/library.js"></script>
<script defer src="/js/app.js"></script>
<!-- Independent, runs whenever ready -->
<script async src="/js/analytics.js"></script>
- Use
deferfor classic scripts that depend on each other. - Put deferred scripts in source order: dependency first, dependent script second.
- Use
asynconly when the script is independent. - Multiple async scripts may download in parallel, but execution order is unpredictable.
- Deferred external scripts download while HTML is parsed and execute after parsing completes.
- A normal script at the bottom of
<body>is ordered, but it is discovered later and still blocks when reached. asynctakes precedence if bothasyncanddeferare present on a classic external script.- Test the browser versions you support; unsupported attributes may fall back to normal script behavior.
FAQ
Should I use async or defer for jQuery?
Use defer if another script uses jQuery. Put the jQuery tag before the script that depends on it.
Do async scripts download at the same time?
Browsers can fetch multiple resources concurrently, subject to network and browser scheduling. However, async does not guarantee simultaneous downloads or execution order.
Does defer preserve script order?
Yes. External classic scripts with defer execute in the order in which they appear in the document, after parsing finishes.
Does an async script wait for the DOM to be ready?
No. It executes as soon as it finishes downloading. The document may still be parsing.
Is putting scripts before </body> still valid?
Yes. It remains valid and preserves normal source order. defer in <head> is often preferable because downloads can begin earlier.
Does defer work only in HTML5?
No. It is not limited to HTML5. Support details vary for very old browsers, so use your project's browser-support policy and test where necessary.
Can I use defer and async together?
Do not use both to combine their behavior. For a classic external script, async wins, so ordering is not reliable.
What is the best default for a new site?
For non-module application JavaScript, defer is usually a strong default. For modern applications, type="module" is often appropriate because module scripts are deferred by default.
Mini Project
Description
Build a small page that loads a utility library and application code without blocking HTML parsing. The application file uses a function from the library, demonstrating why ordered loading matters.
Goal
Load two dependent JavaScript files with defer and update a page element after parsing completes.
Requirements
Use two external JavaScript files named helpers.js and app.js.
Load both files in the document <head> with defer.
Make app.js call a function defined in helpers.js.
Display a greeting inside an element with the ID message.
Keep helpers.js before app.js in the HTML.
Keep learning
Related questions
Add a Favicon to a Static HTML Page
Learn how to add a favicon to static HTML pages, use correct paths and icon formats, and troubleshoot browser caching and local-file issues.
Allow Only Numeric Input (0-9) in HTML Input Using jQuery
Learn how to allow only digits 0-9 in an HTML input using jQuery, with examples, validation tips, common mistakes, and best practices.
Apply CSS !important with jQuery .css()
Learn why jQuery .css() cannot set !important and how to use CSSStyleDeclaration.setProperty() to apply inline important styles safely.