Critical Render Path Optimisation — How To Increase Your Page Speed

Abi Travers
Compare the Market
Published in
12 min readApr 5, 2019

--

Introduction

In this article I will be looking at increasing your page speed. Specifically, I will be looking at how to get your page to load in under 3 seconds.

I will be focusing on how to achieve a page load time of under three seconds via optimising your critical render path. I will be looking mainly at one of the main pillars of increasing page speed:

Thou shalt eliminate render-blocking.

What this article is going to cover:

  1. What is page speed and why should you care?
  2. The ten pillars of page speed success.
  3. How does the browser work and what is rendering?
  4. How to reduce render blocking — JavaScript and CSS

1. What is page speed and why should you care?

Page speed is the amount of time it takes for your page to load once a user has requested it. I first heard about reducing page load speed when I was working as a marketer. I remember hearing that:

40% of users will abandon a page that takes more than 2/3 seconds to load.*

* Source Neil Patel, growth hacking expert.

I then started to work for Compare the Market as a junior software engineer and again encountered work on getting the fastest possible page speed.

Why care?

It effects how many users you have on your page, which ultimately means how many customers you have, customers who are paying into a business which pays you as a developer. Also, the more users the more people seeing your work J.

How is page speed measured?

There are a few ways to measure page speed. The measurement most important for getting the under three second page load time is the:

Critical render path

The most important from an SEO perspective, how google measures you in order to rank your page for search queries are:

Critical render path

&

Time to first byte (TTFB).

For the purpose of this article I will be focusing only on the critical render path.

What is the critical render path?

It is the series of events that must take place to render (display) the initial view of a webpage. So the content a user sees when first loading a page, before scrolling. This is also known as the above the fold content.

Some useful definitions:

  • Critical — Above the fold content. The first bit of the page which is displayed immediately.
  • Render — I will go into this in more detail later but for now let’s assume it means when the page can be seen by the user.
  • Path — The chain of events that lead to our webpage being displayed in a browser.

To optimise the critical render path on your site it is important to first understanding what is critical for your webpage to display — the above the fold / initial view content.

2. The ten pillars of page speed

There are 10 key issues which effect page load time. They are known as the ten pillars of page speed and are:

  1. Thou shalt avoid landing page redirects
  2. Thou shalt eliminate render-blocking
  3. Thou shalt enable compression
  4. Thou shalt bundle & minify your CSS
  5. Thou shalt bundle & minify your JavaScript
  6. Thou shalt minify your HTML
  7. Thou shalt prioritise visible content
  8. Thou shalt optimise your images
  9. Thou shalt reduce server response time
  10. Thou shalt leverage browser caching

For the purposes of this talk/article I will be focusing on number 2, “Thou shalt eliminate render-blocking”, therefore optimising the critical rendering path.

3. How does the browser work and what is rendering

What does it take for the browser to render your website?

This diagram shows the components which make up a browser. The components most critical for the rendering path are the rendering engine and networking component.

Let us imagine a user types your website url into the address bar of their browser. The address bar is part of the User Interface component of the browser.

The browser then uses its’ networking component to open up a TCP connection, it then makes an http request to the server which hosts your website. It does this by sending the request off to a DNS server which does a lookup to find the IP address of that url then sends the request to your websites’ server. Your server sends the files which make up your website to the users’ browser.

When the files are sent over it is the rendering engine which is responsible for reading and interpreting them. The rendering engine is responsible for interpreting html documents and images which are formatted using CSS and generating the layout which is displayed by the user interface.

So, how does it parses/ interprets these files:

The stages of the rendering engine

At the parsing stage it creates the DOM from the html and the CSSOM from the CSS.

It creates the render tree from the DOM and CSSOM. The purpose of this tree is to enable painting of the contents in the correct order.

The browser computes the geometry of the layout and its elements from the render tree. The browser paints pixel by pixel the visual representation of the render tree. This is what we see on the screen.

The rendering engine always tries to display the content on the screen as soon as possible. It does not wait for the html parsing to be complete before starting to build the render tree. It parses and displays the content it has received so far from the network while it is still receiving further content.

To put this all into a context I will use an example of a very simple website, made up of just one html file, one CSS file and one JavaScript file.

The path this page takes before it gets displayed is:

  1. The browser opens up the connection to your server and downloads the html file.
  2. Browser begins to parse the html, sees there is a JavaScript file and a CSS file.
  3. Browser realises it cannot display the webpage without the CSS. As it cannot construct the CSSOM model.
  4. Browser fetches the CSS file and parses it. It stops parsing the html and creating the DOM while it creates the CSSOM.
  5. Browser realises it cannot display the webpage without the JavaScript file.
  6. Browser fetches the JavaScript file and parses it. It stops parsing the html and creating the DOM, while it does this.
  7. Browser completes the render tree, layout and paint stage are then completed.
  8. The browser can display the page.

So right now, the CSS and JavaScript are blocking the browser from displaying any of the website, including the above the fold part which is responsible for the critical render path.

This means they are render blocking.

4. How to reduce render blocking

Firstly, JavaScript

When the browser encounters a script tag it stops parsing the html and building the DOM to go off to fetch the JavaScript file and execute it.

The reason the browser does this is because JavaScript can alter and change the DOM and CSSOM. We can add and remove elements, we can modify the CSSOM properties of each element: For Example:

Changing the style of an element:

Altering DOM elements:

It makes sense for JavaScript to be render blocking as the browser doesn’t want to continue creating something which it may then have to re-create once it has the JavaScript.

Another reason that JavaScript can be render blocking is if it contains the following code:

Document.write causes a total re-render so it is best to avoid it if you want to increase page speed and improve performance.

There is good news though, you can stop JavaScript from blocking rendering in two ways:

1st Improving your loading strategy.

2nd Never use document.write().

3rd Wrap your non-critical JavaScript execution in an onLoad Event to ensure it doesn’t execute until after the page has loaded.

How to improve your loading strategy

Normal script tag

Image from google developer: http://bit.ly/2NMerGi

First let’s understand what is going on when you use a normal script tag and place it at the bottom of your page.

You would use this type of loading when your JavaScript file is fundamental to the above the fold of your page. For example, if it was creating or styling html elements which would be above the fold, so in the critical rendering path. Or the JavaScript needed to enable lazy loading of images.

Async scripts tag

With the async attribute, the browser parses the html, gets to the script tag while still parsing the html. When the JavaScript file is fully downloaded it reads and executes it, pausing html parsing as it does so.

Think of async tags as a way of sending a signal to the browser that it does not need to execute this file at its’ exact point of reference, so it can continue creating the DOM until execution.

Examples of when you would use the async attribute is when your script file is not dependant on other files and does not have dependencies itself. For example, self-contained analytics scripts.

The reason you could not asynchronously load JavaScript files with dependencies on other JavaScript files is because you cannot know when the file will be executed and, if you have multiples, in what order.

Defer script tag

The defer keyword allows you to asynchronously load a JavaScript script file then defer its’ execution until after the DOM and CSSOM model have been created.

The browser fetches and parses the file the same as for async, in parallel to html parsing. However, it waits until the completion of html parsing for execution.

This means that the rest of your content can load faster and you’re above the fold and the critical render path will be completed sooner.

You would use defer for below the fold interactivity and critically, when script tags need to be placed somewhere other than the bottom of your html file.

Async and defer are pretty widely supported through most browsers apart from old versions of IE.

You should use defer for the majority of your scripts to stop render blocking. For scripts which stop other resources render blocking such as lazy loading of images, no tag is preferred. Async can be used for some analytics scripts if they are needed very soon on in the page loading journey.

Wrap the execution of the rest of your Javascript so it executes after the onLoad event

To guarantee your JS does not block rendering, you must do this with your script itself, making sure the bulk of it is not executed until after it hears the onload event.

CSS

CSS is responsible for the styling of your page.

The browser parses the CSS and transforms it into the CSSOM, the CSS Object Model.

CSS is render blocking because without it the browser would not know how to layout the render tree or display the page. CSS is critical to displaying your page.

Generally, your website will access this information in one of two ways:

  1. In an external file, shown in the above example.
  2. In-line written within your html file.

To optimise your critical render path and to delivery critical (above the fold) content to your user as fast as possible you must deliver the CSS responsible for styling this area as fast as possible.

You must also ensure that the rest of the CSS does not block the beginning of the page rendering by somehow deferring it’s loading.

Deliver above the fold CSS as fast as possible

If your CSS is all in an external style sheet, like the example above, the browser has to make additional http requests to get it. This means the browser has to stop parsing the html to go through the process of opening a network connection and asking for the resource.

The best way to deal with this is to in-line this CSS. In-lining means put it straight into your html code. Example:

It will be found by your browser sooner and it can start creating the CSSOM responsible for your above the fold content quicker.

Stop the rest of the CSS from blocking the critical rendering path

In-lining all your CSS is a bad idea for overall page speed performance. This is because the browser does not cache in-line CSS so everything must be loaded from scratch ever time the user comes back to your site.

The best way to ensure the bulk of your CSS, loaded in a separate style sheet, does not block rendering, is with a loading strategy similar to that for JavaScript which causes the CSS loads in parallel to rendering.

You can do this with the rel= ”preload” attribute which looks like this:

Contrasted with the usual:

The preload value of the link element’s rel attribute allows you to write declarative fetch requests in the <head> section of your html. So before the browser starts rendering the page and parsing the html it has already fetched the resource, so the resource is not blocking it.

Preload works because it removes the stylesheet tag temporarily. The stylesheet blocks rendering as the browser assigns it high priority and stops parsing the to fetch and parse it.

It allows you to asynchronously load CSS, not blocking the rendering of the rest of the page and most critically the above the fold, critical rendering part of the page.

Not all browsers support preload tags. But in these browsers you can still load your non-critical CSS asynchronously by using Polly filler libraries such as LoadCS.js.

5. Conclusion

The Criticial Render Path

Optimising the critical render path can take seconds off your page load time. It is really the quickest path to faster webpages. It is what has the most impact on your customers and on your google search performance.

To a large degree, “optimising the critical rendering path” refers to understanding and optimising the dependency graph between HTML, JavaScript and CSS.

We looked at the best way to do this through eliminating render blocking JavaScript and CSS resources:

  • JavaScript — Use async for critical JavaScript only and defer for all other scripts.
  • CSS — In-line your critical CSS within the head of your html. Asynchronously load your main CSS with the preload value for the rel attribute of the style element.

Doing all this can significantly improve performance and your page speed scores, ensuring that time to first render achieves the under 2 second rule.

This article is the script I wrote for a talk I did on increasing your page speed at JS Monthly.

This article can also be found on my personal blog site HERE.

https://www.meetup.com/js-monthly/events/257742345/

--

--