The performance impact of JavaScripts: how to minimize it by using “defer” or “async” attributes
Modern websites make significant use of JavaScripts. The performance impact of javaScripts on digital experience will vary depending on how you implement them.
From a performance perspective, the main challenge of using JavaScripts is that they are “render-blocking”. When your browser parses the HTML file and comes across a <script>...</script>
tag, it must stop the DOM building process in order to fetch and execute the script. In case of an external script (<script src=”...”>
), this can dramatically impact the overall user experience.
The performance impact of JavaScripts placed in the <head>
Usually, scripts are placed in the <head>
portion of the page.
In this case, the HTML parsing process looks like this:
The parsing is paused until the script is fetched and executed. Then it resumes.
JavaScripts placed in the <head>
will directly impact loading metrics like LCP.
The performance impact of JavaScripts placed in the <body>
One simple solution to solve this problem consists of placing the script at the very end of the <body>
part of the page.
In this case, the HTML parsing process does not pause . The script is fetched and executed when the parsing process is done and the DOM is ready. In this case, it will not impact your loading metrics like Page Load Time and Largest Contentful Paint.
It seems so easy to solve the problem! Why not systematically place all scripts at the end of the body then? Well, there are two main drawbacks using this technique:
- First, it is only valid in case the script can be executed after the DOM is ready.
Let’s take the example of the Kadiska RUM JavaScript. If this script is executed way after the page is fully loaded, you take the risk of missing some first performance metrics because some events would happen before the JavaScript execution starts.
- Second, depending on the network conditions (latency, packet loss) as well as script size, fetching it can take a relatively long time, delaying the execution of the script.
Using Defer and Async to manage the performance impact of javaScripts
Fortunately, techniques exist to minimize the potential impact loading JavaScript may have on performances: defer and async.
Both are boolean attributes that are used in a similar way:
<script defer src=”your-script.js”></script>
<script async src=”your-script.js”></script>
Both techniques pursue the same goal: avoiding to block the DOM building process by interrupting the HTML parsing.
Most modern browsers support these techniques (https://caniuse.com/script-async).
What is “Defer”?
When using the defer attribute, the browser does not wait for fetching and executing the script to parse the HTML and build the DOM. The script loads in the background and then runs when the DOM is fully built.
In this case the script does not block the browser’s main thread and is executed when the DOM is ready.
Compared to placing the script at the end of the <body>
tag, this improves the performance by fetching the script while parsing the HTML.
Nevertheless, the script is still executed when the DOM is ready, which can be a problem in some cases, like mentioned before.
What is “Async”?
When using the async attribute, the script is completely independent. It means that:
- Fetching the script does not block the HTML parsing process
- Executing the script can happen before or after the DOM is ready. When executing before the DOM is ready, the HTML process is paused while executing the script.
- An async script does not wait for other scripts.
Example of async script executed before DOM is ready:
Example of async script executed after DOM is ready:
When your script does not rely on others and you do not have to ensure it loads and executes before the DOM is ready, async is a very good solution.
Takeaways
When your JavaScript execution is not needed for rendering critical content of the page (which is for example the case for Google Analytics), using either defer or async attribute can greatly enhance user experience.
Defer has the advantage of never blocking the HTML parsing, while async has the advantage of loading the script independently of others.
If you found this article relevant, there is a great chance that you find this article on the interactivity metrics:
- Interactivity: how to improve FID – First Input Delay
- What’s Time to Interactive and how to improve it