Interesting history
- In the way-back days of Javscript, the function document.write() was the only way to have Javascript interact with the web page. As such, when the web page came across a request for a Javascript file to load, the browser had to put everything else on hold -- just in case the Javascript file used document.write to inject something into the stream.
script tags are parser-blocking
- So, When a browser’s HTML parser finds a script tag, it knows that the tasks in this script might alter the page’s render tree, so the browser pauses its parsing and DOM construction to let the script download and run completely. Once it’s done, the browser will resume the parsing and DOM construction from where the HTML parser left off. That's why, script files are called Parser blocking.
Entering async and defer
- This is why modern web browsers have a defer and async attributes.A way to prevent JavaScript from blocking the parser and renderer is to mark the script tag a as synchronous. This limits our access to the DOM (no document.write) but lets the browser continue parsing and rendering the site regardless of the execution status of the script.
<script src="main.js" async></script>
<script src="main2.js" defer></script>
async attribute
When you add the async attribute to your script tag, the following will happen
<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
- Make parallel requests to fetch the files.
- Continue parsing the document as if files are downloaded.
- The moment the files are downloaded, pause the parsing and execute the scripts
- then continue the parsing
defer attribute
defer is very similar to async with one major differerence. Here’s what happens when a browser encounters a script with the defer attribute.
<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
- Make parallel requests to fetch the individual files.
- Continue parsing the document as if it was never interrupted.
- Finish parsing the document even if the script files have downloaded.
- Execute each script in the order they were encountered in the document.
Note : Moving script calls to the end of the page and making them asynchronous helps with perceived performance by optimizing your critical rendering path and eliminating those render-blocking issues.