Written by Jeffrey Bennett

When you include JavaScript on your webpage, the DOM rendering engine must first parse the data before displaying the page to the end-user.

That is unless you load in your JavaScript asynchronously. But which of the many ways to do this are best?

Let's compare techniques with my side project SVG Match, shall we?

First, I'll start by using inline JavaScript to load in the external files. This will execute as soon as the DOM parser discovers the code.

<script>
var script = document.createElement("script");
script.src = "main.js";
document.getElementsByTagName("body")[0].appendChild(script);
</script>

ProTip: Only use <scriptsrc="main.js"></script> if you absolutely must execute your JavaScript files immediately. This will block page rendering until it's downloaded, parsed, and executed!

Now, let's postpone executing the bulk of the code until page load.

<script>
window.onload = function() {
	var script = document.createElement("script");
	script.src = "main.js";
	document.getElementsByTagName("body")[0].appendChild(script);
};
</script>

Better, but I'm obsessed with performance these days. Let's go further.

<script async defer>
window.onload = function() {
	var script = document.createElement("script");
	script.setAttribute("async", "async");
	script.setAttribute("defer", "defer");
	script.src = "main.js";
	document.getElementsByTagName("body")[0].appendChild(script);
};
</script>

Now that the async and defer attributes are on the <script> tag itself, the rendering engine will postpone any JavaScript execution until necessary (for the browsers that support these attributes, ahem Internet Explorer 😝). This allows the DOM parser focus on the critical rendering path with HTML and CSS.

Getting even better, but let's go further.

This original JavaScript file is around 58KB in size. Not big at all compared to most webpage assets these days, but it's still more than I need at the start. So I'm breaking this JavaScript file into two parts.

First, I'll execute the part with the page layout and get that on screen, then asynchronously load in the rest directly from the first-requested JavaScript file. That will bring the first JavaScript file down to around 10KB.

Let's see how this compares to the original:

[waterfall screenshot of before and afterwards]

Yaaaaaaassssss!! We have it! Even though we now have more HTTP requests, the perceived performance is significantly better. 100ms is the threshold for "feeling instant." And perception is 9/10th of reality, as they say. 😜

So, how can you improve the performance of your own website? Very often, you can postpone loading in your JavaScript files until the browser is ready for them. Just be careful when you do this if you have more than one because dependent scripts may load and execute out of order, causing JavaScript parsing errors.

If you absolutely must execute certain scripts in order, concatenate your dependent files together.

If you like what I've written, follow my updates on Facebook, Twitter, or by RSS feed. This blog is brand-new, so it would be super fantastic if you would share it with your friends and colleagues! Thanks for reading!

Life is too short for bad websites!

Read my bio