Javascript’s defer vs async attribute

Flashbacks of vanilla javascript cloud my mind – back when we didn’t have Jquery. All we had was Javascripts’ event listener method to detect whether the entire DOM was loaded before scripts were fired off.

Why was this necessary though? Well, if you’re a developer you very well know – page speed. And back in those days, programmers weren’t so mindful of placing external javascript files – the head section, footer and I’ve seen some sprinkled throughout the body. Not optimal at all – this can have huge negative implications in terms of functionality and speed.

So in the beginning, we programmers used something like this to defer scrips from executing.


document.addEventListener("DOMContentLoaded", function(event) {
    // Your code to run since DOM is loaded and ready
});

We even used variations of attaching the load event directly onto the window object…


window.addEventListener('load', 
  function() { 
    alert('hello!');
  }, false);

Then along came jQuery…


$(document).ready(function() {
    console.log("Ready!");
});

Don’t get me wrong these are all awesome – I to this day still use a variation of these methods depending on the situation. And if you’re a programmer – there are a whole lot of situations we run into nowadays. I find that my degree in Economics has helped gain insight on not only the right tool, but the optimal tool for the job.

So in my consulting experience – I’ve run into situations where I had direct access to the source code. Meaning, in the context of optimizing a site, ie. page speed. In most cases, the site was small enough that I could safely move external scripts from the header to the footer section – where they should be.

Now this was all good and dandy during those days – a lot of sites were powered by your usual HTML, CSS, Javascript and PHP to handle server side processes. But nowadays we’ve got all sorts of CMS platforms – namely WordPress, Squarespace, not to mention all eCommerce platforms like BigCommerce and Shopify. Right, what about PHP frameworks like Laravel, Symfony. Then there’s Javascript frameworks like VueJS and AngularJS. Look, the list goes on – I’ve seen them all.

It wouldn’t be so difficult if you (the programmer) had full control – you could make changes as you wish. But in the case of consulting – you run into situations where moving one script could break an entire site. Was the optimization worth it? Furthermore, is minification even worth it? When down the road, you have deep pages that don’t function the way they did.

So what I propose is a careful assessment of the sites architecture. It all goes back to architecture. But that statement is short lived when it’s not your architecture and all you have to work with is a bloated site, a bloated architecture. Examples of this are sites that load way too many plugins (ie WordPress), libraries and scripts in an inefficient manner.

Alright back to the “defer” attribute – let me cut to the chase. In situations where I have limited freedom – I use the “defer” attribute.

It’s usage goes something like this. Be mindful, this only works for external javascript elements.


<head>
<script src="script.js" defer></script>
</head>

Notice this script is placed in the head section. What this “defer” attribute will do is execute after the page (DOM) has completed loading. Pretty awesome. See now we don’t have to move this script down to the footer section (below the body). Note that I only resort to this when I have limited freedom, or, moving a script would result in breaking the site.

Okay… now on to it’s sidekick. Yeah “defer” has a sidekick – the “async” method. This one is an interesting entity.

When using “async” – the script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing).

Yeah super interesting. I currently don’t know situations where this is more advantageous than just using the “defer” attribute. But if you’re looking to implement both, here’s how it’s done:


<head>
<script src="script.js" defer async></script>
</head>

Yeah, you just plugin them both in and you’re good to go. Cheers!