JS INSiGHTS  - Dealing with Render-Blocking Javascript

JS INSiGHTS - Dealing with Render-Blocking Javascript

Β·

12 min read

Heya fellows, Shobhit here and welcome to the very first chapter of JS INSiGHTS In this article, I am gonna talk about async and defer attributes that are basically used to enhance the loading of javascript files in your code.
Let's get started πŸ”₯

TL;DR ⏳

Async - Scripts having async attribute downloads in the background and executes as soon as they are downloaded. The relative order of scripts is not maintained. Useful for independent third-party scripts.
Defer - Scripts having defer attribute downloads in the background and are executed only when the whole DOM content is built. The relative order of scripts is maintained. Useful for scripts depending upon each other
Browser support -
Defer : 97.5% support
Async: 97.3% support.

Table of Contents πŸ“ƒ

Script Tag without async or defer 🧐

At some point in our life as a developer, we all have worked with HTML, CSS and JS. Several times, we have written <script src="sample.js"></script> without caring about the UX, the loading time it is going to take, blocking of parser etc.

Let's take a glimpse at how our browsers parse HTML. Browsers follow the top to bottom approach while parsing an HTML code. As it encounters the <link> or <img>, it sends out an asynchronous request. This means that our browser will not wait for the image or link to load. It will continue its parsing and the image will be loaded in the background. We all have observed this thing at some point. But the case is not the same with <script>. As our browser encounters the <script>, it stops parsing and this is what we call render-blocking javascript.

Noram Javascript Execution Generally speaking, the browser needs to load a queue of JS files before the user can see the main content. Now, if you have too many of these JS scripts which will delay the main HTML content from loading. This, in turn, slows down your website and forces the users to wait.

Well, the solution to this is very simple. If we put script tags at the bottom of our HTML code i.e after </body>, then the browser will first parse the whole HTML code and then it will load our scripts. And it might happen that a user is clicking on a button and that button is not responding as it's JS file is still downloading.

Hence, this solution will work well for small HTML files but it's far from perfect for a larger codebase.
So, let's welcome attributes of the hour πŸ₯ πŸ₯ Async & Defer.

Async Attribute 🧨

  1. Using async attribute, instructs the browser not to stop while parsing <script>. This means the parser will download the JavaScript in the background and continue parsing as normal without waiting just like <img>. But, when our image is downloaded, it just appears. JS doesn't work in this way. As soon as our javascript code is downloaded, it is executed by the Javascript engines. Asynchronous javascript execution

  2. This is great for any small JavaScript code. When the javascript code is executed, parses stops parsing the HTML file. So the parser could still be delayed by JavaScript that takes a long time to execute.

  3. Disadvantages: A huge downside of async scripts is that they run in "load-first order". This implies that whichever script will load first, will execute first. Suppose we have two scripts.
    <script src="long.js" async></script>
    <script src="small.js" async></script>
    
    Let's assume that the small script is dependent upon the long one. But, as the former will download earlier, it will start executing thereby producing errors.
    So, if your scripts are dependent upon each other, I will recommend not to use async attribute.
  4. Advantages: The browser doesn’t block on async scripts at least while downloading and it will also not block if your JS file is short to execute. Async scripts are great when we integrate an independent third-party script into the page.

Defer Attribute πŸ’£

  1. Defer attribute is somewhat like async as it also tells the browser not to wait for the script. The browser will continue to process the HTML and building the DOM. But, here comes the plot twist. Scripts with defer attribute will execute only when the DOM is fully built. That means unlike the async attribute, the defer attribute will not execute the JavaScript until after the entire HTML document is parsed and hence our parser will never be blocked.
    Defer javascript execution
  2. Loading JavaScript with the defer attribute is essentially the same as loading JavaScript at the end of the body, but it will start the download sooner. Also, if your javascript code has event handlers, then you should not use async as it might happen that your code will try to attach the handler to a DOM element that is still not parsed. I will recommend defer in this case.
  3. Advantages: A huge advantage of defer is that it maintains the order of javascript files while executing. Since the JavaScript is executed after the entire HTML document is parsed the order of the JavaScript files is maintained. This is because all defer attribute JavaScript files must be downloaded before any of them can be executed.
  4. Disadvantages: There is no such disadvantage of using defer attribute but it doesn't make any sense loading an independent third-party script (google-analytics) using defer attribute.

Dynamic Scripts ✨

Another way to include scripts is to create a script and append it to the document dynamically using JavaScript. Dynamic Scripts behave as "async" by default.

function loadScript(src) {
  let script = document.createElement('script');
  script.src = src;
  document.body.append(script);
}

loadScript("sample.js");

Classic, Modular and Inline Scripts

  • Classical script is the one that has the src attribute. It's a standard JavaScript script as you know it. For classic scripts, async and defer will behave as explained above.
  • Module Scripts were introduced in ES6 version of javascript. When we include a JS file having import or export keywords in our HTML file, then we have to set type = module inside script tag.
    Module scripts defer by default i.e. using defer will have no effect on module scripts. If you don't want to load module script and all its dependencies after the whole parsing has been completed, you can use async attribute.
  • Inline scripts are the ones that aren't exported from an external resource. They are defined and embedded inside HTML only. Both async and defer has no effect on the inline scripts.

Conclusion 🎯

If you have dependent scripts or if you want your script to run after the whole DOM content is build the use defer. If you have independent third-party scripts use async. In special circumstances, async tags can be useful for speeding up your page load.

πŸ“£ Always keep in mind not to use async and defer if your scripts tag are present at the bottom of HTML code i.e. after </body>.

TIPS πŸ’‘

  • Both async and defer are Boolean attributes. The presence of a boolean attribute on an element represents the β€œtrue” value and the absence of the attribute represents the β€œfalse” value.

  • If you use both async and defer attribute then the later one will act as a fallback. <script src="https://www.google.com/reca..." async="" defer=""></script>

  • The DOMContentLoaded Event Exception:

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

Hence, the scripts with defer attribute will always execute before the DOMContentLoaded event.

While in case of async, DOMContentLoaded may happen both before or after async.

Exercise πŸ€“

A tiny bit of exercise so that you can test yourself whether you have understood the concept or not.
Which attribute would you use in the following scripts?

// Google Script
<script src="https://google-analytics.com/analytics.js"></script>
// jquery CDN 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
// AdSense
<script src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

The answers will be revealed in my next article, till then stay tuned.

Well, Thanks for reading and if you want more such content do subscribe to my newsletter. Also, you can follow me on Twitter to get daily updates about the web world πŸ€—