Make your website load fast. Improve web render (repaint) speed

We were challanged to improve the time to first paint (aka First Meaningful Paint) of a client's shopify theme. Study 34 has a beautiful mission for people who care about the provenance of product in the fashion industry, starting with modern, sustainable, luxury knitwear for women. However, tested on slow speed mobile connections we identified the time to first meaningful paint was well over 1 minute! This was (once spotted) an obvious barrier to their mission and needed addressing.

Constrained by the Shopify eco system this forced us to work out exactly what affects the time visitors must wait before being able to see/use your website. We broke things, we fixed them, and we ended up with a faster time to first paint.

Why bother?

Percieved perofrmance affects sales. If your pages load slower, you will get less sales. Check your site works on slow connections & slow performance devices.

It's all too easy with website builders such as Shopify to choose a beautiful theme, slap in even more beautiful apps for functionaly without even testing the speed of the site for your visitors. Yes, is might work fine for you on your big iMac in the office, but you're customers are likly one their mobile phone, with a flakley connection and don't have time to wait. Put yourslf in your customers environemtn, because this is how they truly experience your website.

  1. What realistiacally are we in control of?
    • If you run your own site, you've not got to worry about shopify as much: but external scripts are always a factor so make sure you deal with these
  2. Measure first. You must set a benchmark to work with
  3. Look for areas which will save you the most time
    • This kind of work is very time consuming but fun! Don't waste hours optimising something to save 5ms when another optimisation can save you 17 secconds.

We've ordered these headings in an 'order of most returns first'. Starting with Less Bytes, Faster Renders (the less bytes you send, the faster everything will be). Then into detail of what to do next.

Less Bytes, Faster Renders

Remove unnecessary cruft (minify).

Deliver all CSS as fast as possible

This is why less bytes matters most, the bits you never have to send best never sent!

The Browser can only render as soon as it has all CSS & has built the CSSOM. CSS is render blocking. In order to paint the page, the browser needs to create the render tree - and it can only do that once it's parsed the CSS it's fetched/fetching. Two things are needed before a first paint:

  1. The DOM tree
  • The Cascading Stylesheet Object Model (CSSOM)

Also note that CSS blocks Javascript execution, so without all your CSS having been delivered, the browser will block running your JS until all CSS has loaded (because it needs that in order to build the CSSOM).

Javascript which alters your HTML causes your DOM to rebuilt, again, triggering a re-paint. So keeping JS as nimble as possible, affecting as few nodes as possible is key.

All of this is why putting your CSS at the bottom of the page is a bad idea. If you do this, the browser till block (wait) until it has downloaded everything else, then the CSS, then build the CCSSOM. Meanwhile you'll have a blank screen.

Use media attribute to speed up first paint

Separate out your CSS files, you can use the media="" attribute to signal to the browser that the CSS within that file are only for that media query. e.g:

<link rel="stylesheet" href="styles-media-max-770px.css" media="max-width: 770px">

Would signify to the browser not to block going to build the CSSOM if the screen size is > 770. Note the file would still be downloaded, but your render wouldn't be held up generating parsing a CSS file which is irrelevant to the users dimensions. See the video exerpt from Google/Udemy course explaining this: https://youtu.be/IevppzdhumA

How to stop Javascript blocking rendering

Not all js edits the DOM. But the browser doesn't know this so will block unless you tell it otherwise!

Either:

1. Add the async attribute to your non-dom changing js scripts e.g:
<script src="randomScript.js" async></script>
2. Edit your script an wrap an onload event around it e.g:
wdocument.addEventListener("load", function() {
  //This code won't run until all resources have downloaded.
  init();
  doSomethingElse();
});
3. Don't inline your JS

Putting your js inline will still block the render; there is one exception to this which is if you put it before any CSS <link> or inline CSS. The browser will block on all other inline js it finds.

Ask yourself: Which requests are blocking rendering

The Critical Rendering Path (CRP) can be blocked by

  • JS which is not marked as asynchronous but should be
  • JS which is inlined, and therefore blocks rendering until complete

async your iframes

iFrames are blocking, they're popular on fashion websites; you might find a video on your homepage (e.g. youtube iframe embed) is greatly slowing down the time-to-first paint. This is because the browse is waiting for the entire iFrame to load before it begins painting. We've seen a whole 6 seconds knocked of an otherwise blank homepage on slow connections.

Further Reading

avoid-large-complex-layouts-and-layout-thrashing

https://github.com/wilsonpage/fastdom

https://www.youtube.com/watch?v=b7SUFLFu3HI

Karma Computing helps growing & independent businesses automate and compete in the modern world.