Gerben van Diggelen
6-6-2017

Boost the Google pagespeed of your Umbraco website - part 1/3

Google uses loading speed of a website as a ranking factor, especially on mobile. This means that a slow website might move your site down in Google’s search results list. Besides that: we all hate waiting for a web page to load, right?

Google has provided us with a page speed test called PageSpeed Insights. This blog is the first of a three part series in which we describe what measures you can take to boost your Umbraco website speed and thus also your PageSpeed score.

In this part:

  • We explain how you can bundle and minimize your external resource files
  • We explain how to remove render-blocking JavaScript files 

Bundle and minimize Javascript and CSS

Google PageSpeed Insights suggestion: Minify CSS and Minify JavaScript

One of the first and most easy to follow advices to improve the speed of your Umbraco website, is to bundle and minimize any used JavaScript and CSS files. As you may or may not know, bundling means that externally loaded files will be combined into one, resulting in less HTTP requests and thus improved loading time. Minifying is a kind-of-magical process removing all not-needed characters and white spaces, resulting the code to be not really human-readable anymore, but smaller in file size.

For our projects, we use SquishIt to automate the bundling and minifying. It is also possible to use the native ASP.NET MVC bundling/minifying, but in our experience ASP.NET MVC bundling sometimes is erroneous when it comes to combining files that contain certain CSS constructions.

It is easy to install SquishIt using NuGet with the following command:

Install-Package SquishIt

Then, in your Razor view / Umbraco template, add the following code and make sure you add each of your external JavaScript files that are needed:  

@Html.Raw(Bundle.Javascript()
.Add(“/script1.js”)
.Add(“/script2.js”)
.Render("~/Script/combined_#.js"))

This will render in the following HTML tag:

<script type="text/javascript" src="/Script/combined_E76D22A254623F517794A5399BCF4DCA.js"></script>

The combined file will contain the minified version of file script1.js and script2.js.


Notes, hints and caveats

Requires additional folder permissions
SquishIt writes the bundled and minified files to the folder as specified in the Render method call. Make sure this folder has sufficient permissions. 

SquishIt only bundles and minifies if the application is not in debug mode.
So make sure the debug flag is set to false in web.config:    
<compilation defaultLanguage="c#" debug="false">

As an alternative, add the method call ForceRelease() to your code.

@Html.Raw(Bundle.Javascript()
.Add(“/script1.js”)
.Add(“/script2.js”).
.ForceRelease()
.Render("~/Script/combined_#.js")) 

This will make sure that SquishIt always bundles and minifies, even if the application is in debug mode. Note this instruction will always combine and minify the files, even on your development machine which could be annoying if you are debugging JavaScript.


Remove render-blocking Javascript 

Google PageSpeed Insights suggestion: Eliminate render-blocking JavaScript and CSS in above-the-fold content

When a page loads it always tries to download the entire page and externally linked files before rendering the page. This means that the browser first has to load the external JavaScript and CSS files, before something can be displayed to the user. This will cause a penalty in the Google PageSpeed analyses.

To remedy this we can tell browsers that some files do not take priority and can be downloaded after rendering the page.  We can do this  “async” tag on the JavaScript row making it look as follows:
<script src=”/js/script.js” async></script> 

Since we are using SquishIt to combine the files and generate the script tag, we need to instruct SquishIt do add the async attribute as follows

Html.Raw(Bundle.JavaScript()
.Add(“script1.js”)
.Add(“script2.js”)
.WithAsyncLoad()
.Render(“/script/combinedScript_#.js”)

 This will render in the following HTML tag:

<script type="text/javascript" src="/Script/combined1_7026413A9C8D58E1F9B7C907D8C5B45A.js" async></script>


Notes, hints and caveats

Timing of loading and order of executing
Loading JavaScript in an asynchronous way, might affect the moment when the JavaScript files are loaded and  executed. This will get you into trouble when there are dependencies between the files and the bundling is disabled. In the example below, we use the jQuery library. Our own script (script.js) uses some functions of the jQuery library. 

Html.Raw(Bundle.JavaScript()
.Add(“jquery.js”) // jQuery library
.Add(“script.js”) // Our own script file, uses jQuery
.WithAsyncLoad()
.Render(“/script/combinedScript_#.js”) 

This will result in the following HTML (if bundling is disabled)

<script type="text/javascript" src="jquery.js" async></script>
<script type="text/javascript" src="script.js" async></script>

 You are likely to get JavaScript errors in your console now, since chances are that script.js is loaded and executed first before jQuery is loaded. 

In order to solve this, you can use the defer attribute if you want to make sure that the files are loaded in order. Defer scripts are guaranteed to execute in the order that they appear in the document.

Html.Raw(Bundle.JavaScript()
.Add(“jquery.js”) // jQuery library
.Add(“script.js”) // Our own script file, uses jQuery
.WithDeferredLoad()
.Render(“/script/combinedScript_#.js”)

This will result in the following HTML (if bundling is disabled)

<script type="text/javascript" src="jquery.js" defer></script>
<script type="text/javascript" src="script.js" defer></script>

Read more about the meaning and differences of defer and async on this page

Caching
SquishIt will cache the resulting HTML tag that comes out of the Bundle.Javascript() functionMake sure you restart your Umbraco site (by touching web.config) after you added methods like .WithDeferredLoad().

Alternatives
In this blog, we use SquishIt to help us do the minification and bundling. As with most technologies, there are alternatives you can use to achieve the same result. Here are two of them that we know of:

Meer weten?
Neem contact op met Gerben.

Gerben van Diggelen
Operationeel directeur
[email protected]