Javascript

What is the loading and execution order of JavaScript scripts in a web page

25 September 2026 · 11 min read

What is the loading and execution order of JavaScript scripts in a web page

Understanding how JavaScript loads and executes is crucial for building performant and interactive web pages. A poorly structured script can lead to slow loading times, unresponsive elements, and a frustrating user experience. This post delves into the intricacies of JavaScript’s loading and execution order, providing you with the knowledge to optimize your website’s performance and create a seamless user journey. We’ll explore the various factors that influence script behavior and provide practical tips for managing your JavaScript effectively.

The Basics of JavaScript Loading and Execution

By default, JavaScript execution follows a simple, synchronous order: scripts are loaded and executed in the order they appear in the HTML document. When the browser’s parser encounters a

This basic behavior can be modified using attributes like async and defer, offering more control over when scripts are downloaded and executed. Understanding these attributes is key to optimizing script delivery and minimizing the impact on page load times.

For instance, a script that handles user interactions on a specific element might not be necessary until after the entire page has loaded. Strategic placement and the use of attributes can prevent these scripts from hindering initial load times.

The Impact of the async Attribute

The async attribute instructs the browser to download the script asynchronously, without blocking HTML parsing. This means the script downloads in the background while the rest of the page continues to load. Once the script is fully downloaded, the browser pauses HTML parsing to execute it. Multiple async scripts can download concurrently, significantly improving page load performance.

However, using async doesn’t guarantee a specific execution order. If multiple async scripts are present, they will execute as soon as they finish downloading, which can lead to unpredictable behavior if scripts have dependencies on each other. It’s best to use async for independent scripts that don’t rely on other scripts for their functionality.

Consider a website incorporating social media widgets or analytics scripts. These are often independent units that don’t affect core page functionality. Using async for these scripts is a best practice to prevent them from delaying the main content load.

The Role of the defer Attribute

The defer attribute also instructs the browser to download the script asynchronously, but unlike async, it guarantees that scripts are executed in the order they appear in the HTML document. deferred scripts are executed after the HTML parsing is complete but before the DOMContentLoaded event is fired.

This attribute is ideal for scripts that depend on the DOM being fully constructed but don’t need to block the initial page rendering. Using defer ensures that scripts execute in a predictable manner, minimizing potential conflicts and errors.

For example, a script that manipulates page elements or attaches event listeners should ideally be deferred. This ensures the script executes after the elements are available in the DOM, preventing errors and ensuring the script functions as expected.

Best Practices for JavaScript Optimization

Optimizing JavaScript loading and execution is crucial for a smooth user experience. Strategically placing

  • Place
tag for scripts that don't need to execute immediately.
  1. Use async for independent scripts, such as analytics scripts and social media widgets. Employing these techniques ensures that your JavaScript code runs efficiently without hindering the overall user experience. This contributes to better search engine rankings and keeps users engaged with your website.

Consider using a Content Delivery Network (CDN) to serve your JavaScript files. CDNs cache files closer to users geographically, reducing latency and improving download speeds.

  1. Identify critical scripts that are essential for initial page rendering.
  2. Defer loading non-critical scripts until after the main content has loaded.
  3. Use tools like Lighthouse to analyze your website’s performance and identify areas for improvement.
  • Minify and compress JavaScript files to reduce their size and improve download times.
  • Use a build tool like Webpack or Parcel to bundle multiple JavaScript files into a single optimized file.

Understanding JavaScript’s loading and execution sequence is key to crafting a performant web experience. By implementing the strategies outlined here, you can optimize your website’s speed, improve user engagement, and boost your search engine rankings. Learn more about website performance optimization on web.dev.

“Optimizing JavaScript is not just about speed, it’s about creating a seamless user experience,” says Addy Osmani, Engineering Manager at Google. This sentiment underscores the importance of understanding how JavaScript impacts the user journey.

[Infographic Placeholder: Illustrating the loading and execution flow with async and defer]

For further information on asynchronous JavaScript, explore resources like MDN Web Docs and JavaScript.info.

Learn more about front-end development.FAQ: JavaScript Loading and Execution

Q: Does the order of

A: Yes, the order matters, especially if you’re not using async or defer. Scripts are executed in the order they appear in the HTML.

By mastering JavaScript loading and execution, you are empowered to create a faster, more efficient, and user-friendly web experience. This knowledge is fundamental for any web developer seeking to build high-performing websites that cater to today’s demanding online landscape. Explore the provided resources and begin optimizing your JavaScript today to see tangible improvements in your website’s performance and user engagement. Dive deeper into the world of JavaScript and discover how you can leverage its power to build truly exceptional web experiences. Consider exploring related topics like optimizing images, leveraging browser caching, and implementing efficient CSS delivery for a more holistic approach to web performance optimization.

Question & Answer :
There are so many different ways to include JavaScript in a html page. I know about the following options:

  • inline code or loaded from external URI
  • included in <head> or <body> tag [1,2]
  • having none, defer or async attribute (only external scripts)
  • included in static source or added dynamically by other scripts (at different parse states, with different methods)

Not counting browserscripts from the harddisk, javascript:URIs and onEvent-attributes [3], there are already 16 alternatives to get JS executed and I’m sure I forgot something.

I’m not so concerned with fast (parallel) loading, I’m more curious about the execution order (which may depend on loading order and document order). Is there a good (cross-browser) reference that covers really all cases? E.g. http://www.websiteoptimization.com/speed/tweak/defer/ only deals with 6 of them, and tests mostly old browsers.

As I fear there’s not, here is my specific question: I’ve got some (external) head scripts for initialisation and script loading. Then I’ve got two static, inline scripts in the end of the body. The first one lets the script loader dynamically append another script element (referencing external js) to the body. The second of the static, inline scripts wants to use js from the added, external script. Can it rely on the other having been executed (and why :-)?

If you aren’t dynamically loading scripts or marking them as defer or async, then scripts are loaded in the order encountered in the page. It doesn’t matter whether it’s an external script or an inline script - they are executed in the order they are encountered in the page. Inline scripts that come after external scripts are held until all external scripts that came before them have loaded and run.

Async scripts (regardless of how they are specified as async) load and run in an unpredictable order. The browser loads them in parallel and it is free to run them in whatever order it wants.

There is no predictable order among multiple async things. If one needed a predictable order, then it would have to be coded in by registering for load notifications from the async scripts and manually sequencing javascript calls when the appropriate things are loaded.

When a script tag is inserted dynamically, how the execution order behaves will depend upon the browser. You can see how Firefox behaves in this reference article. In a nutshell, the newer versions of Firefox default a dynamically added script tag to async unless the script tag has been set otherwise.

A script tag with async may be run as soon as it is loaded. In fact, the browser may pause the parser from whatever else it was doing and run that script. So, it really can run at almost any time. If the script was cached, it might run almost immediately. If the script takes awhile to load, it might run after the parser is done. The one thing to remember with async is that it can run anytime and that time is not predictable.

A script tag with defer waits until the entire parser is done and then runs all scripts marked with defer in the order they were encountered. This allows you to mark several scripts that depend upon one another as defer. They will all get postponed until after the document parser is done, but they will execute in the order they were encountered preserving their dependencies. I think of defer like the scripts are dropped into a queue that will be processed after the parser is done. Technically, the browser may be downloading the scripts in the background at any time, but they won’t execute or block the parser until after the parser is done parsing the page and parsing and running any inline scripts that are not marked defer or async.

Here’s a quote from that article:

script-inserted scripts execute asynchronously in IE and WebKit, but synchronously in Opera and pre-4.0 Firefox.

The relevant part of the HTML5 spec (for newer compliant browsers) is here. There is a lot written in there about async behavior. Obviously, this spec doesn’t apply to older browsers (or mal-conforming browsers) whose behavior you would probably have to test to determine.

A quote from the HTML5 spec:

Then, the first of the following options that describes the situation must be followed:

If the element has a src attribute, and the element has a defer attribute, and the element has been flagged as “parser-inserted”, and the element does not have an async attribute The element must be added to the end of the list of scripts that will execute when the document has finished parsing associated with the Document of the parser that created the element.

The task that the networking task source places on the task queue once the fetching algorithm has completed must set the element’s “ready to be parser-executed” flag. The parser will handle executing the script.

If the element has a src attribute, and the element has been flagged as “parser-inserted”, and the element does not have an async attribute The element is the pending parsing-blocking script of the Document of the parser that created the element. (There can only be one such script per Document at a time.)

The task that the networking task source places on the task queue once the fetching algorithm has completed must set the element’s “ready to be parser-executed” flag. The parser will handle executing the script.

If the element does not have a src attribute, and the element has been flagged as “parser-inserted”, and the Document of the HTML parser or XML parser that created the script element has a style sheet that is blocking scripts The element is the pending parsing-blocking script of the Document of the parser that created the element. (There can only be one such script per Document at a time.)

Set the element’s “ready to be parser-executed” flag. The parser will handle executing the script.

If the element has a src attribute, does not have an async attribute, and does not have the “force-async” flag set The element must be added to the end of the list of scripts that will execute in order as soon as possible associated with the Document of the script element at the time the prepare a script algorithm started.

The task that the networking task source places on the task queue once the fetching algorithm has completed must run the following steps:

If the element is not now the first element in the list of scripts that will execute in order as soon as possible to which it was added above, then mark the element as ready but abort these steps without executing the script yet.

Execution: Execute the script block corresponding to the first script element in this list of scripts that will execute in order as soon as possible.

Remove the first element from this list of scripts that will execute in order as soon as possible.

If this list of scripts that will execute in order as soon as possible is still not empty and the first entry has already been marked as ready, then jump back to the step labeled execution.

If the element has a src attribute The element must be added to the set of scripts that will execute as soon as possible of the Document of the script element at the time the prepare a script algorithm started.

The task that the networking task source places on the task queue once the fetching algorithm has completed must execute the script block and then remove the element from the set of scripts that will execute as soon as possible.

Otherwise The user agent must immediately execute the script block, even if other scripts are already executing.


What about Javascript module scripts, type="module"?

Javascript now has support for module loading with syntax like this:

<script type="module"> import {addTextToBody} from './utils.mjs'; addTextToBody('Modules are pretty cool.'); </script> 

Or, with src attribute:

<script type="module" src="http://somedomain.com/somescript.mjs"> </script> 

All scripts with type="module" are automatically given the defer attribute. This downloads them in parallel (if not inline) with other loading of the page and then runs them in order, but after the parser is done.

Module scripts can also be given the async attribute which will run inline module scripts as soon as possible, not waiting until the parser is done and not waiting to run the async script in any particular order relative to other scripts.

There’s a pretty useful timeline chart that shows fetch and execution of different combinations of scripts, including module scripts here in this article: Javascript Module Loading.