Script Loading Strategies
There are a number of issues involved with getting scripts to load at the right time, which creates unexpected bugs and errors.
Hello, I am Krish Jaiswal and this is my first blog post. Here I will be telling you about some <script>
loading strategies while coding which reduces the chances of errors.
Whenever I would code, I used to place the <script>
tag (external way) either in the <head>
tag or just before the </body>
tag.
Today I learnt that both the ways are not suitable and there are better strategies of loading the script. Let's learn about it. #webdevelopment
"All HTML is loaded in the order in which it appears."
Hence, when we place the <script>
tag inside the <head>
, it means that the script will be loaded before the HTML has been parsed which could cause errors if the script is used to manipulate elements on the page.
The solution to the problem is to use this structure:
'DOMContentLoaded'
document.addEventListener('DOMContentLoaded', () => {
...
});
--> This is an event listener which listens to the event 'DOMContentLoaded'
which states that the script will be loaded only when all the HTML has been parsed.
NOTE: This method can be only used when the script is placed internally. You cant use this method when you are placing the script externally.
When the <script>
is placed externally:
To solve the problem of Html being loaded after the script, 2 ways can be used:
1) defer
2) async
Lets look at them in detail:
Consider that there are 3 JS files in your project to be loaded in the following order:
<script src="js/vendor/jquery.js"></script>
<script src="js/script2.js"></script>
<script src="js/script3.js"></script>
Defer
<script defer src="js/vendor/jquery.js"></script>
<script defer src="js/script2.js"></script>
<script defer src="js/script3.js"></script>
It fetches/downloades the script in the background while not disturbing the Html from being loaded. It waits for the Html to be loaded and only after that, the script is executed.
Here the 3 files will be executed only after the HTML is loaded entirely, in the wanted order:
1)jquery.js
2)script2.js
3)script3.js
Async
<script defer src="js/vendor/jquery.js"></script>
<script defer src="js/script2.js"></script>
<script defer src="js/script3.js"></script>
It fetches/downloades the script in the background while Html is being loaded. But it executes the script as soon as it is downloaded (At this time, The HTML parsing is blocked while the script is being executed).
It offers no guarantee of which file will be executed first.
For example: Suppose the script2
and script3
files are loaded before the jquery.js
file, then those files will be executed while the jquery
file is being loaded, hence it will create issues because any functions in those scripts depending on jquery
will produce an error because jquery
will not be defined at the time the script runs.
You might be thinking that why not we put the script
just before the body tag.
This will work but this is also not the most suitable way to load scripts because fetching of the script is completely blocked until the HTML DOM has been loaded. On larger sites with lots of JavaScript, this can cause a major performance issue, slowing down your site.
It becomes much clear when all the information written in this blog is read in the context of this visual representation:
CONCLUSION:
1) It is to be noted that both async
and defer
instruct the browser to download the script(s) in a separate thread, while the rest of the page (the DOM, etc.) is downloading, so the page loading is not blocked during the fetch process.
2) Scripts with an async
attribute will execute as soon as the download is complete. This blocks the page and does not guarantee any specific execution order.
3)Scripts with a defer
attribute will load in the order they are in and will only execute once everything has finished loading.
4)In the external case, we did not need to use the DOMContentLoaded
event because the defer
attribute solved the problem for us. We didn't use the defer
solution for the internal JavaScript example because defer
only works for external scripts.