a. You will be sure that the page has been rendered and the DOM was loaded before you run any JS.
b. Head element gets loaded before body, so page rendering will not be blocked by waiting for JS files to be downloaded if we put all our JS right before </body>.
But there is more to this, so let's get things explained a bit more.
Putting external JS tags in <head>
Normally external scripts <script src="..."> are loaded and executed synchronously, so the main disadvantage of referring to external JS scripts is that these files need to be downloaded before page rendering can continue.
Imagine that if we had something like this:
<head> <script src="somejs.js"></script> </head> <body> <p>some paragraph</p> </body>
, then our paragraph would be rendered only after somejs.js file had been loaded.
async and defer attributes make changes
Without async or defer scripts in <head> get loaded and executed immediately when they are found in your <head> tags. This obviously pauses rendering of the rest of page while those scripts are loaded and executed. And this is exactly the reason why it's suggested to put your external scripts right before </body>.
But if we add either async or defer, it means that our scripts first of all get downloaded asynchronously, not blocking HTML parsing. This is promising, but let's find out about async and defer in more details.
If we use async like <script src="..." async> then this means the script will be downloaded parallel to html page parsing and executed immediately after it's loaded. Script loading will not cause any delay in HTML parsing, because async means asynchronous download. HTML parsing will only be paused for the script execution period.
A good use case to use async is when we want script to be executed as soon as possible, but we prefer it not to cause any delay in the actual html rendering. One of the most common examples is gogole analytics script, which they recommend to load by using async to track page visits even if the use has left the page before it was fully loaded.
Because scripts with async attribute are being loaded in parallel, there is no guarante in the order of how files get loaded. If you have 2 scripts and second file needs to rely on the first one, like for instance some jQuery plugin needs to rely on jQuery being loaded, just don't put async on first file load. async doesn't guarantee script execution order.
By using defer we instruct browser to execute script only after HTML parsing had completed (right after DOMContentLoaded event ). Script download is in parallel to HTML parsing, so as with async it is non-blocking.
Scripts with defer attribute execute similarly to async with the difference that async means the script will be executed immediately after it's been loaded, while defer defers script execution until DOMContentLoaded event.
In constrast to async, using defer guarantees script execution order.
Why I still suggest putting your external scripts before </body> ?
Even if we assume everyone uses html5 supporting browsers, which async requires, by putting our extenal JS scripts in <head> and using either async or defer still has some disadvanages:
- HTTP has limited number of concurrent requests, so if the page has many image, their loading will be delayed until the scripts are loaded.
- Even if there is a low number of parallel requests and not many images need to be loaded, downloading scripts in parallel to HTML parsing means script files and image files will be sharing bandwidth, which in turn means slower image loading speeds.
- Loading scripts with async attribute means there is not a rea
In the majority of cases you don't need to use async or defer, because HTML parsing will still take the same time if you put your scripts before </body>.
By putting your scripts before </body>, it can only take a little bit more time to load them, but that would also safe bandwidth and a limited number of requests for loading images, so for a short period of time page can fail to respond properly without scripts, but this is another story and maybe a good place to start investing time into PWA.