async & defer attributes in Script Tag

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 fol­low­ing will happen

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Make par­al­lel requests to fetch the files.
  2. Con­tinue pars­ing the doc­u­ment as if files are downloaded.
  3. The moment the files are downloaded, pause the parsing and execute the scripts
  4. then continue the parsing

defer attribute

defer is very sim­i­lar to async with one major dif­fer­er­ence. Here’s what hap­pens when a browser encoun­ters a script with the defer attribute.

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Make par­al­lel requests to fetch the indi­vid­ual files.
  2. Con­tinue pars­ing the doc­u­ment as if it was never interrupted.
  3. Fin­ish pars­ing the doc­u­ment even if the script files have downloaded.
  4. Exe­cute each script in the order they were encoun­tered 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.