This is an error that can take 30+ points from your score and it is one of the hardest to fix on a mature website.
This is the second installment of my series of blog posts on Google PageSpeed Insights optimizations and recommendations. This time we are going to focus on what is render-blocking JavaScript and how to eliminate it.
Part 1: Google PageSpeed Insights optimizations and recommendations
Part 3: Eliminate render-blocking CSS in above-the-fold content
Google wants to start rendering the upper half of the page (above-the-fold) without waiting to download resources, especially if they are used after you start scrolling the page. To put it simply, if you do not see the page footer, you do not need anything related right away.
It is a good practice to move scripts right before the closing body tag </body>
. By Google’s recommendation, most, if not all, external JavaScript <script>
tags should have an async attribute. In other words, the JavaScript files will execute asynchronously with the rest of the page. This way is great if you have no dependencies like jQuery or other libraries.
Placing a <script>
tag with async attribute right before the closing body tag </body>
is imperative because execution can start before HTML is parsed and the targeted DOM element may not exist.
On our website, for instance, I’ve placed all scripts at the bottom of the page:
<script src="/jquery.js"></script>
<script src="/owl.carousel.js"></script>
<script async src="/script.js"></script>
jQuery is added without async or defer attribute to make sure that is loaded first.
Do not put an attribute on an external script that is being used by another script. I have added async to all my other external JavaScript like Bootstrap, etc.
A general rule of thumb is if the JavaScript file is used by other, do not use an async attribute because you cannot be sure which file will download first.
There are some cases that you will use or have a library in your JavaScript code that has for example jQuery as a dependency. For me, it was Owl Carousel. I am using Owl’s initialization method in my JS file to create carousel slides.
To dive deeper into the following cases, we will use the scripts from the example above.
My script.js is using jQuery, Owl and is not used by any other script. Owl has jQuery dependency.
To make sure we call first jQuery, second Owl and last script.js we can put async attribute only on script.js.
Case 1: What if you want to make Owl non-blocking?
If you are using the library somewhere below-the-fold, the PageSpeed tool probably won’t say anything. However, if you are using it as the homepage slider, there is little you can do.
Solution 1: Load the library as internal JavaScript, not as an external file.
<script src="/jquery.js"></script>
<script>
/* put the owl carousel code here */
</script>
<script async src="/script.js"></script>
Well, this looks bad as the HTML document will become more substantial, and the Prioritize visible content error might occur.
Solution 2: Import the library into the script.js file.
<script src="/jquery.js"></script>
<script async src="/owl-and-script.js"></script>
This is a better solution, but still far from the best, because you might need to download second time the library on a page that is not loading the script.js file.
Solution 3: You will not like it, and it is time-consuming, but if you need something simple, try writing carousel yourself or at least find library without jQuery dependency.
Conclusion: I choose to leave alone the Owl library because otherwise it will need additional work for support and page loading time was not improved much better. However, if you need to fix this render-blocking resource and one of the three solutions should do the job or at least guide you to a better one.
Case 2: What if you want to make jQuery non-blocking?
Solution: Please do not, you will create more problems than to fix. Even Google does not know how to do it right, saying:
Investigate making such JavaScript asynchronous or defer its loading. (reference)
While it is not difficult to make jQuery non-blocking resources, it is a nightmare to support it, and we must weigh the overall pros and cons.
Important: JavaScript that modifies a DOM element located above-the-fold will be a render-blocking resource. To prevent that JavaScript code must be within <script>
tags.
It is unacceptable to inline whole jQuery library into the HTML document, but remember that most of the time it is render-blocking because another script is changing the DOM through jQuery and Case 2 might be Case 1.
Final words about JavaScript
Don’t go crazy with the score. Sometimes some projects are so entwined with JavaScript libraries that it is impossible to satisfy PageSpeed tool without significant changes.
Next, we will focus on how to eliminate render-blocking CSS in above-the-fold content.