<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.
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.
<head> will directly impact loading metrics like LCP.
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.
- 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.
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.
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