
Optimising gatsby‑image Even Further

Although not a direct drop‑in replacement for an <img/> tag, gatsby‑image is a simple React component which is specifically designed to work with Gatsby's GraphQL queries and native image processing/transformations. It uses these capabilities alongside some very clever image‑loading techniques to vastly optimise image loading on‑site. No doubt if you are reading this, you are already familiar with both Gatsby and gatsby‑image, but suffice it to say: it is an absolute must‑use for projects developed in Gatsby.
Whilst I won't dive too deeply into how it works (the official documentation is here for a more in‑depth read), the basic idea is that you use GraphQL to output a set of images and pass it to the component. When the page first loads the component displays a blurred, very low‑resolution, inlined Base64 version of the image and then uses Intersection Observer to determine when an image is needed and loads in the higher‑resolution version, giving that trademark 'blur up' effect as you scroll the page.
Whilst this is incredibly efficient and clever, there are two very low‑effort steps that I always take to increase the performance (or ‑ in one case ‑ perceived performance) yet further.
Only Use as Much Image as You Need
It might seem obvious, but this is one I come across more than anything else when picking up another developer's work. The larger the dimensions of your image, the bigger the file size, and the slower the load. gatsby‑image does some very smart things with the image srcset to help the browser determine which image to load, but this is only as intelligent as the image data fed to it.
The Gatsby Image API provides a set of query parameters that you can use to resize an image right in your GraphQL query. Put bluntly: if you are not using these in your queries, then you are not optimising your images.
Whilst the focus of this article is on improving ‑ yet further ‑ perceived image load times it is important to note that the default values for these parameters are generally quite low, so setting these may in actual fact increase your file size slightly, but will probably improve the rendering of the image in return.
There are two key parameters I focus on in my projects:
Maxwidth
If you are using a fixed query, then this would simply be width, and could even be combined with height, but I most commonly use fluid queries: my sites are responsive, so the size of space an image takes up on‑screen is determined by width rather than by height and often changes if you resize the browser. This is a simple int, in pixels, and defaults to 400, which I expect may well be very low for many people's needs.
If you take away nothing else from this article, take away this: the value you pass here is the maximum physical size of your image, on screen, in pixels. Do not be tempted to double it up to account for retina screens, gatsby‑image already does that for you so you will just end up serving images multiple sizes too large for your visitors.
Quality
This is ‑ again ‑ a simple int which you can essentially think of as a percentage: 100 is totally lossless compared to the original, whilst at 0 probably won't allow you to identify what the image even contains. By default, this is set to 50 which I personally feel is a little on the low side, especially as a lot of the freelance work I use Gatsby for tends to be fairly image‑heavy so I tend to be nearer 80 or even 90. Nevertheless, you can tweak this upwards and downwards until you find a value that works for your content.
All combined together, use your GraphQL query to ensure that the image assets you are passing through to gatsby‑image are already as optimised as possible: the right dimensions, and the right quality.
Your query should look similar to:
image { childImageSharp { fluid(maxWidth: 800, quality: 80) { ...GatsbyImageSharpFluid_withWebp } }}Use the Browser's Native Loading Attribute
One of the props gatsby‑image accepts is loading. This is passed straight through to the eventual <img/> element rendered on‑page and allows you even further finite control over when an image should actually be loaded by leveraging the browser's built‑in loading capability. You can read about it in much more detail on Google's own blog here, even if you aren't using gatsby‑image, you should still be using this on your images!
For the sake of our discussion, the one thing that really surprised me when asking for feedback from clients was that the opinion over whether the blur‑up effect was desirable or not was split very evenly and generally on the extremes. On one side, some felt it was the coolest feature in the world, whilst others very strongly opposed it: one person even went as far as to say that they would never hire a developer whose website did that!
So, the answer lies in the perceived loading speed of the image: people don't want to see the image blurring into view, they want the image already there and ready to look at by the time they reach it on the page.
Enter loading="eager". By setting the loading prop to eager, you are signalling to the browser that the image should be loaded more urgently, which bypasses any other lazy‑loading options and ensures that the image loads as soon as is possible.
Your JSX should look something similar to this:
<Img fluid={image.fluid} alt="lorem ipsum" className="lorem__ipsum" loading="eager"/>The nice thing about this approach is that it is using the browser's native capabilities rather than relying on JavaScript to determine when an image ought to be loaded. This ensures that everything else page‑critical is still loaded first, but that there is no further delay in loading the images, even if off‑screen.
Despite the image not actually loading any more quickly than it might otherwise, they certainly appear to. Using this in conjunction with gatsby‑image means that you get the best of both worlds: images in view will still blur up as they load (something you probably see in the hero image at the top of this article when you first arrived), whilst every image below the fold should already be there by the time you scroll to them.
Related Articles

Using Regex to Replace Numbers in a String. 
The CSS overflow Property. The CSS
overflowProperty
Installing Gatsby onto an M1 MacBook Air. Installing Gatsby onto an M1 MacBook Air

React Fragments Explained. React Fragments Explained

Optimising Vue.js Performance with Lazy Loading and Code Splitting. Optimising Vue.js Performance with Lazy Loading and Code Splitting

Single or Double Colons in CSS Pseudo‑Elements (:before vs. ::before). Single or Double Colons in CSS Pseudo‑Elements (
:beforevs.::before)
Using Vue's Suspense for Asynchronous Components. Using Vue's Suspense for Asynchronous Components

Automatically Generate Text Sitemaps in Gatsby. Automatically Generate Text Sitemaps in Gatsby

Promises in JavaScript: An Introduction. Promises in JavaScript: An Introduction

Asynchronous Module Definition (AMD) in JavaScript. Asynchronous Module Definition (AMD) in JavaScript

Understanding Signals in Angular: The Future of Reactivity. Understanding Signals in Angular: The Future of Reactivity

Removing p Tags from Contentful List Items. Removing
pTags from Contentful List Items