Improving page speed and core web vitals on Shopify stores

← Blog

This week, I deployed some page speed/core web vitals updates to my clients Shopify website. I’ve been working on it for a few weeks now, tweaking code and assets here and there wherever I can – it’s been an interesting task.

But rather than me regurgitate what everyone else is writing about lately (and there’s a lot of it around!), I thought it would be more beneficial to summarise the updates I made and include links to reading materials that I found helpful.

Handle CSS render-blocking better

I’ve been using Sass a lot over the last few years, but to improve page speed and render-blocking in particular, I decided to convert the Sass stylesheet to standard CSS, i.e. remove the reliance on Sass altogether.

In doing so, I discovered the Sass compiled CSS was a mess, partly caused by the ease of creating nested styles in Sass and my ignorance of what Sass was compiling it into.

So, I refactored all the CSS (by hand, not using any tools other than my code editor, etc.) and then divided the styles into multiple minified files based on the media queries. These files were then linked to in the head with the media attribute. I initially added the critical CSS as inline styles within the document head, but it didn’t improve performance that much – probably because the file was relatively small.

Useful reading:

  1. https://developer.mozilla.org/en-US/docs/Learn/Performance/CSS

Move all scripts to the end of the body

I had already done this when I first built the site, but it was worth double-checking anyway. Placing the scripts at the end of the document allows the page content to load first.

Async or Defer scripts

Deferring scripts allows the elimination of render-blocking Javascript, i.e. the page doesn’t have to load and execute scripts before it finishes rendering.

Async and defer can be confusing at times, but defer is a good option, especially if using jQuery.

Useful reading:

  1. https://www.digitalocean.com/community/tutorials/html-defer-async

DNS prefetching

Before the browser can request a resource from a server, it needs to make the connection which involves multiple steps from origin to destination and depending on network conditions; a single round trip might take a significant amount of time.

A solution for this is to implement rel=preconnect and rel=dns-prefetch within the document head.

Useful reading:

https://web.dev/preconnect-and-dns-prefetch/

If you have a website you’ve not made any updates to for a long time and uses Google fonts, it’s worth checking the font URL contains &display=swap as per Google’s latest version.

I was previously including Google fonts using the @import CSS rule as it felt more cleaner with all dependencies in one place, but this method causes the browser to process CSS more slowly because it has to download the imported files thus blocking the rendering process. So, it’s best to use the <link rel="stylesheet"> tag.

I also decided to review font usage as this particular website used two fonts, each with multiple weights; Poppins for headings and Roboto for body text. The more weights you declare, the more fonts are loaded, thus increasing resource size. Therefore, I replaced Roboto with the default system font.

Useful reading:

  1. https://blog.logrocket.com/5-tricks-to-eliminate-render-blocking-resources/
  2. https://css-tricks.com/os-specific-fonts-css/#update-september-2016

Optimise images

Image compression and “shrinking” is a must-do for all website images, and there are plenty of tools out there to aid with this – tinyPNG is my personal favourite.

But there is more to it than just image compression. With responsive website design, it’s common not to include width and height attributes in <img> tags to allow resizing. Adding them helps the browser render more quickly and prevents the dreaded layout shift issue (where content jumps because it’s still loading). Adding the width and heights effectively tells the browser to reserve this space for an image whilst the page is still loading.

It’s also beneficial to use the srcset and sizes attributes when working with responsive images, so the browser loads the best size appropriate to the device. I managed to implement this very easily in Shopify using the built-in image filters.

It’s also worth examining the content-visibility: auto; property which can help reduce CPU work the browser must do by lazy-rendering offscreen content. See the first link listed below for more information. Although, this can also increase Cumulative Layout Shift (CLS), so it’s worth testing before implementing it as a solution.

Lazy loading images is also worth implementing.

Useful reading:

  1. https://www.smashingmagazine.com/2021/04/humble-img-element-core-web-vitals/
  2. https://developers.google.com/speed/webp/docs/using
  3. https://github.com/marketplace/imgbot
  4. https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
  5. https://github.com/ApoorvSaxena/lozad.js

Converting jQuery to vanilla javascript

I’ve been using jQuery since it was first released ten years ago, and I’ve relied on it ever since. I’m no javascript expert, but I can write vanilla javascript without the need for jQuery, but using the latter just sped up the build process for me.

I haven’t removed it for this project yet (it’s in the next round of changes), but I did convert it on my website and saw an increased performance, so it’s definitely something I will be removing as a dependency from all existing client websites.

Useful reading:

  1. https://tobiasahlin.com/blog/move-from-jquery-to-vanilla-javascript/
  2. https://github.blog/2018-09-06-removing-jquery-from-github-frontend/
  3. https://youmightnotneedjquery.com
  4. https://css-tricks.com/now-ever-might-not-need-jquery/

So that concludes the first round of changes I made to improve page speed and website performance. I’ll be sure to summarise the second round of changes when I achieve them.

Subscribe to my newsletter

Sign up to get my latest blog articles direct to your inbox.