By default JavaScript files are blocking. They create a blank screen during their loading is loaded in the head of the page without any optimization.
How to check if the website contains blocking JavaScript?
Test the website on PageSpeedInsight and look for this warning “Eliminate render-blocking JavaScript in above-the-fold content”. The tool will list the blocking files but I recommend you to double-check in the source code. To do so, look for JavaScript files loaded at the top of the page that don’t contain any defer
or async
attributes.
How to fix?
There are a couple of ways to fix this issue. One of the best methods is to place the scripts at the bottom of the page and add a defer
attribute.
Non-optimized:
<script type='text/javascript' src='./app.js?ver=1.10.1'></script>
Optimized:
<script type='text/javascript' src='./app.js?ver=1.10.1' defer></script>
You may want to use the async
attribute, which does almost the same thing except that defer
will preserve the execution order.
Use async
if your script doesn’t depend on any other scripts (like Google Maps SDK); otherwise, use defer
.
NB: If you see defer
and async
used together, it’s because this was a technique for browsers that did not support defer
. Nowadays ALL browsers support defer
.
Pitfalls
Most of the time, developers know that loading a script in the head is a bad practice, but sometimes they feel forced to do it.
Common pitfall: Inline JavaScript in the HTML
JavaScript can be executed in an external file but also inside the HTML between two script
tags. If you decide to move some JavaScript files from the top to the bottom and add a defer
attribute, the website can break because of unsatisfied function definitions due to inline JavaScript.
How to fix that?
There’s a way to defer inline JavaScript by using this piece of code:
window.addEventListener("DOMContentLoaded", () => {
var arr = document.querySelectorAll("script[type='defer']");
for (var x = 0; x < arr.length; x++){
try { eval(arr[x].innerHTML); }
catch (e) { if (e instanceof SyntaxError) console.log('[ERROR] ', e); }
}
});
This code will defer the inline JavaScript and wait for all the scripts to be loaded and executed before executing inline scripts.
Example
<h1>Hello</h1>
<script defer src='./jQuery.js'></script>
<script>
$(document).ready(function() { $('h1').append(' world !'); });
</script>
This example will generate an error because we call the $
function before it’s defined due to the defer
attribute (the $
function is defined in jQuery.js
).
Example
<h1>Hello</h1>
<script type="defer">
// We added type="defer" to the script tag
$(document).ready(() => $('h1').append(' world !'));
</script>
<script defer src='./jQuery.js'></script>
<script>
// code snippet
window.addEventListener("DOMContentLoaded", function() {
var arr = document.querySelectorAll("script[type='defer']");
for (var x = 0; x < arr.length; x++){
try { eval(arr[x].innerHTML); }
catch (e) { if (e instanceof SyntaxError) console.log('[ERROR] ', e); }
}
});
</script>
This example will work because we wait for the $
function to be defined before executing the code.
- We add the attribute
type="defer"
to the inline JavaScript script. - We add the code snippet mentioned above.
When all the scripts are executed, the code will replace our custom inline scripts with standard scripts.
Common pitfall: One of the blocking scripts is an A/B testing script
If one of the blocking scripts is an A/B testing script (ABtasty / Optimizely / Kameloon / Maxymiser, etc.), it’s normal for this script to block the page; otherwise, it will create a flickering effect.
How to fix that?
- Don’t load the script on mobile if no mobile tests are running.
- Load the script only on pages where tests are running (a small test on the backend will work).
Cet article How to remove Blocking JavaScript on your website ? est apparu en premier sur Antoine Brossault.