Optimizing Javascript Loading: Underasting async, defer and module scriptsIntroIn today's web applications, how you load JavaScript can significantly impact your site's performance. The timing and manner in which scripts load affect everything from initial page rendering speed to interactive readiness. When scripts load inefficiently, they can block HTML parsing and delay critical rendering pathsleading to poor user experiences with slow-loading pages and delayed interactivity. However by following the right strategies, we can dramatically increase the perceived performance in our apps. Some of the most common techniques are: a) asynchronous loading, b) deferred execution, c) and proper script placement in combination with either of the above Regular Scripts vs. Module Scripts: The Basics
Regular ScriptsRegular scripts (<script> tags)Regular scripts (<script> tags) are the traditional way to include JavaScript in an HTML file. They can be either inline (internal) or external. When the browser encounters a regular script, it must pause HTML parsing to load and execute it. For external scripts, this delay is longer since the file needs to be fetched before execution. With inline scripts, the delay is shorter because the script is already in the HTML, so only execution time affects parsing. External Regular ScriptsThis is the most common way how to refernce javascript. It keeps clean separation of concerns, performant friendly and more secure.
Internal Regular ScriptsInline regular scripts are not very common and for security reasons should be mostly avoided. Some common use cases are Google Tag Manager, A/B Testing, Feature Flags, small performance optimizations like inline critical css and font-loading.
Module ScriptsModule scripts (<script type="module">) are a modern way to organize JavaScript using ES6 import/export syntax. They improve code structure, manage dependencies efficiently, and support tree-shaking(removing unused code). Unlike regular scripts, modules load only once, preventing redundant requests. Since not all browsers support modules, a fallback is recommended. They can be eitherinline or external, though external module scripts are more common. They’re especially useful inlarge-scale applicationswhere files depend on each other and they are bundled together. External Module ScriptsExternal Module Scritps sometimes are used without bundling in several practical scenarios such as: development environments, small to medium size applications, educational projects, progressive enhancement where modular functionality is added to specific parts of otherwise traditional websites.
Inline Module ScriptsInline Module Scripts are not very common but still can be used in some cases such as prototyping and demos, educational contexts to demonstrate ES module concepts, progressive enhancment where module features, small applications where setting up build process would be overkill.
Optimisation Technique - Async Attribute"Load Immediately, Execute ASAP"In this technique, we add the async attribute to external regular scripts, allowing them to load in parallel while the browser continues parsing HTML. However, async has no effect on inline scripts and should generally be avoided in module scripts, even though it’s technically possible.
Benefits:
Best Use Cases:
Placement: In the <head> section for analytics that need to run as soon as possible and in the body section for tracking scripts that aren't time sensitive. Optimisation Technique - Defer Attribute"Load in Order, Execute After Parsing"In this technique, we add the defer attribute to external scripts, allowing them to be fetched in parallel with HTML parsing but ensuring they wait to execute until after the HTML is fully parsed. Unlike async, where scripts execute as soon as they’re available, defer ensures scripts execute in order.
Scripts with type="module" are automatically deferred, meaning they behave similarly to deferred regular scripts. Benefits:
Best Use Cases:
Placement: • Regular scripts with the defer attributeare usually placed in the <head> but can be placed anywhere. • Module scriptscan be placed in either <head> or <body>, though <head> is more common, as they are deferred by default. • Bundled scripts (Vite, Webpack) are typically placed at the end of the body. Comparing Loading TimesIn the visualisation below you can see how HTML parsing is disrupted in all different script cases. The blue line in module scripts has some off-main track branches because of the dependencies. These branching patterns in module scripts represent how the browser handles dependencies — fetching imported modules in parallel while continuing to parse HTML.
The Most Common Pitfalls & How to Avoid Them
|