Regular VS async VS defer script loading ⬇
Tags: javascript, webdev, performance, html
Published: 2020-12-11 10:21:32

We have always been advised to put out script tags at the end of the body tag, but have you ever thought why is that so? and is there any other place we can put our script tag?

Well, yes, we can put the script tags anywhere we want but it affects the page performance. We can put the script tag as we normally do inside the `<head></head>` tag of the HTML document  like: 
```HTML
<!-- inside the head tag -->
<head>
    ...
    <script src="scriptURL/PATH"></script>
</head>
```
or at the end of `<body></body>` tag:
```HTML
<!-- at the end of body tag -->
<body>
    ...
    <script src="scriptURL/PATH"></script>
</body>
```
Now let's try to explain the difference.

When a page loads on the browser, the browser starts to parse the HTML, and when it reaches the script tag, it will load the script then execute it.

When we put the script tag inside the `<head></head>` tag, the browser will reach to script tag before parsing the body. It stops parsing HTML for the sake of loading and executing the script. After the execution of the script is over, it will continue parsing HTML. Hence, our page loads slow and we may even get an error because DOM is not created completely yet. 

In the latter case, when we put the script tag at the end of the body tag, first the HTML is parsed and then the script gets fetched and executed. Huh, now we know why we put script tags at the end of the body tag (for performance and avoiding errors).

HTML5 provides 2 new ways for loading scripts, that is async and defer attributes that can be added to the script tag. Adding these attributes when we have our script tag at the end of the body tag, doesn't make much sense (adding them is almost the same as not adding them). But, let's understand what they do when the script is inside the `<head></head>` tag.

##Async attribute
Adding the `async` attribute to the script tag tells the browser to load or fetch script asynchronously while it is parsing the HTML. Whenever the script is loaded, it will get executed, so this way we reduce the time needed for the page to load.

##Defer attribute
The `defer` attribute also tells the browser to load or fetch script asynchronously while it is parsing the HTML. Whenever the script is loaded, it will not get executed until HTML is not loaded and parsed completely.

Wait, if `async` and `defer` does almost the same job, why we have both of them? 
Well, it seems like that, but there are some differences between `async` and `defer`.

`async` doesn't guarantee that scripts will get executed in the order they are written in HTML (the sooner script is fetched, the sooner it is executed), and also `DOMContentLoaded` event doesn't wait for the execution of the async scripts to be fired (`DOMContentLoaded` event gets fired once the HTML is completely loaded and parsed).

On the other hand, `defer` guarantees that scripts will run in the order they appear in the HTML file and the `DOMContentLoaded` event gets fired after all the scripts are loaded and executed.

In conclusion, we can say that we should use `defer` when the order of execution of scripts is important and/or the scripts rely on DOM being parsed fully. `async` can be used for scripts, for which order of execution is not important and it does not rely on DOM.