How to Defer Parsing of JavaScript
When speeding up your website two things have the biggest impact.
- Optimize your images and lazy load
- Defer parsing of JavaScript
The first is easy to understand. The second is much more difficult to get a handle on.
What exactly is defer parsing of JavaScript?
This article is going to cover how to defer parsing of Javascript.
This is a complex subject.
Even if you decide not to attempt this yourself. This article will allow you to talk with confidence to your developers.
We are going to cover:
I encourage you to learn what defer parsing of JavaScript means. Yet for those in a hurry jump to how to defer parsing of JavaScript in WordPress.
Let's dive in.
What is Defer Parsing of JavaScript?
There are four ways you can load JavaScript on you HTML page:
- Inline JavaScript - This means that JavaScript is in the HTML between a
<script>
tag. - External Script - An external JavaScript file and then load it with the src attribute
<script src="">
- Async Script - Like the above except we add an async attribute to the tag
<script src="" async>
- Defer Script - Like the above except we add an defer attribute to the tag
<script src="" defer>
Each of these methods will load the script in a different way which will have an affect on page speed.
It's all about getting the right lego bricks to fit together!
Let's look at each of these methods in more detail to see how they affect the loading of the page.
Inline JavaScript
This is when the JavaScript is inside the HTML. It will look something like this:
<html>
<head>
<title>Inline Script Example</title>
</head>
<body>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-1013XXXXX-1');
</script>
<body>
<html>
The above is an example of loading Google Analytics on a site. This script loads on most of the pages on the internet. Most people don't know that this script will block the loading of your webpage and slow down your site.
This is why Google asks you to put it at the bottom of the webpage. When a browser reads the HTML of your page it goes through each line by line.
This will continue until the page has loaded.
If it finds a script like this it will then stop the processing of the HTML and then run the JavaScript. As JavaScript is running the page cannot finish loading.
Once the JavaScript has finished the browser will continue to load the HTML. It will continue with the next line until the page has finished.
When we defer the parsing of JavaScript, we are trying to eliminate the blocking of the HTML loading.
How do we stop the blocking?
External Script
To load an external script we would use an external JavaScript file using the src attribute <script src="">
If we moved the contents of the Google Analytics script to a file called ga.js
.
It would then load it like this:
...
<script src="ga.js"></script>
...
Is this faster?
Well no, it is slower! The external file must download before it can run. It looks something like this:
The blue bar above is the time it takes for the ga.js
file to download. The red bar is how long it takes to run the JavaScript.
We are now blocking the page from loading while the file downloads and the JavaScript runs.
It would be better if we could download the file without blocking the page.
This is what the async
attribute does.
Async Script
The async
attribute will tell the browser to download in the background.
To make the script async
you would add the attribute to the script tag like this:
...
<script src="ga.js" async></script>
...
The downloading of the file now does not block the HTML:
The file will download in the background and the HTML page continues to load. When the file has finished downloading it will run.
But when it runs it will block the page from loading so we are back to where we started with the inline script!
There is also one other downside with Async. You cannot guarantee the loading order of the JavaScript files. For example, if we had two JavaScript files loading with Async:
...
<script src="a.js" async></script>
<script src="b.js" async></script>
...
There is no guarantee that a.js
will load before b.js
. This is ok if the two files are separate and they don't rely on each other. Yet, if b.js
relies on a.js
then loading these scripts via async
will break your site.
One solution to this is to put all your JavaScript into a single file and then load it with async
.
There is a better way.
Defer Script
The defer
attribute is an attempt to fix all the issues mentioned above.
A script tag that is loading with defer
looks like this:
...
<script src="ga.js" defer></script>
...
When it loads in the browser it does not block the HTML loading at all. The script downloads and queues. Once the HTML has finished processing it will then run the JavaScript:
The best thing about defer is that the order is also kept so if we have this:
...
<script src="a.js" defer></script>
<script src="b.js" defer></script>
...
a.js
will always run before b.js
.
This is how to defer parsing of JavaScript. There are a few other best practices when using defer
.
You want to load the script early so it is best to add the script tags to the <head>
section.
This will get all the files downloading in the background so that they are ready to run once the HTMML has finished.
You should load all scripts on your site using defer
. I do not recommend using a mix of inline, async and defer scripts on the same page. This can confuse leading to a broken page.
A good HTML setup will look something like this:
<html>
<head>
<title>Inline Script Example</title>
<script src="a.js" defer></script>
<script src="b.js" defer></script>
</head>
<body>
...
<body>
<html>
There is a lot of technical detail in this post. Yet it is important to understand how this works. Helping you to spot issues and seek help when needed.
Next, let's look at some tools that you can use to put in place defer loading on your site.
Defer parsing of JavaScript in WordPress
The best plugin to use in WordPress is Async JavaScript by Frank Goossens. He offers great support and is very responsive to enquires.
Once the plugin is installed you can access the settings from the menu:
This will show you some of the options:
Enable the default settings with the “Apply Defer” button. This will set up the default settings for deferring. It may be that some scripts break once you have applied the settings. If they do they you may need to add scripts to the exclusion section:
With this plugin, you want to make sure you load all scripts as external files in the <head>
and add a defer
attribute.
This may mean that you need to change some of the plugins and themes your site is using. If that is the case then you may need to talk to the theme developers and send them this article for guidance.
Deferring Javascript is a complex subject. This is why I recommend using a plugin with great support. Frank will give you help if needed and will offer paid support if your site has a complex setup.
Defer parsing of JavaScript in Shopify
I also wanted to recommend a Shopify app that could help with the speed. Unfortunately, I was unable to find one that I could recommend.
You can, of course, do the above by hand to get defer working.
You would need to edit your theme.liquid
file and find all the script tags on the page.
Then move them to the head and add defer. Always backup your site before doing manual edits!
The risk here will put off many people and I would love to recommend an easier option. If you have a recommendation I would love to test it and add it to this page.
Wrapping Up, How to Defer Parsing of JavaScript
We have covered how to defer parsing of JavaScript. We have seen that there are four ways to do this:
- Inline JavaScript
- External Script
- Async Script
- Defer Script
My recommendation is to have all scripts loaded from external files. Then add the defer
attribute to the script tags.
WordPress users should install Async JavaScript to make this setup easier.
For Shopify, unfortunately, there is no app to install. Instead, you will need to add defer
by hand.
Loading JavaScript for the greatest performance is a complex subject. I hope that after reading this article you have a better understanding of how to add defer.
If you don't want to attempt on your own this article has given you the confidence to speak to your developers.