Speed up your Gatsby site with 1 line of code 🤯

Make your site friendlier and faster by reducing Javascript with a simple trick

TL;DR:

  • Gatsby relies heavily on Javascript through the dependence on React and the addition of a router and other logic to its runtime.
  • Hence, one could argue it's quite bloated for simple static sites, delivering tons of JS that users wouldn't otherwise need.
  • By changing the rendering engine from React to Preact we can reduce up to Xkb (unzipped) in bundle size, making our sites faster on mobile (runtime and loading) and more suited for SEO 🎉

And I finish with a bonus tip at the end, check it out 😉

The problem

Gatsby is great, and I mean it. It has allowed me to build complex sites with ease, such as Data Hackers, and unlock the creative freedom provided by building from scratch without the colossal work needed to build the basis for it, as there are many plugins and great guides out there. Also, it's just React with the added benefit of not having to care about webpack and the likes, so it's quite easy to get productive. In short, it has amazing DX, and it has brought me tons of joy since I started working with it in 2017.

What is not so amazing is its performance. Yes, I'm challenging their homepage slogan.

Shot from the Gatsby homepage featuring the phrase "Fast in every way that matters"
Shot from the Gatsby homepage featuring the phrase "Fast in every way that matters"

First, who even defines what "matters"?! Second, it likes to pride itself in being "blazing fast", that it provides speed by default, to which I agree to a bunch of cases, but not all of them. For a simplistic blog like the one you're reading, Gatsby actually hurts its performance. I'd have to do a terrible job to load 70.9kb of downloadable Javascript (219kb uncompressed) on this very page, and yet, that's what "fast in every way that matters" brings to the table.

Screenshot of Chrome's Network tab showing 70.9kb of downloaded JS for an article in this blog
Screenshot of Chrome's Network tab showing 70.9kb of downloaded JS for an article in this blog

I have a huge collection of thoughts on this and have been delaying a post on the shortcomings and threats of Gatsby for a while, but that will have to wait longer. To finish driving my point home, take a look at my Lighthouse score - measured on applied slow 4G for mobile - for the default Gatsby mode:

Google Lighthouse test on the original Gatsby site using react, showing 340ms as "max potential first input delay"
Google Lighthouse test on the original Gatsby site using react, showing 340ms as "max potential first input delay"

And keep in mind that the document itself is only 10.8kb, including styles, so a TTI of 2.8s for such a simple page is unacceptable (for me, at least 😜). If you want to see it for yourself, here's this version of the page.

The solution: reduce JS through Preact

Turns out Preact X just came out and, with it, came stability and reliability enough to ditch React for Preact as the rendering engine and benefit from the reduced JS. They say a picture is worth a 1000 words, so I'll give you two:

Screenshot of the Network tab showing a JS download size of 40.4kb
Screenshot of the Network tab showing a JS download size of 40.4kb

Lighthouse score of 99 with "Max Potential First Input Delay" of 170ms
Lighthouse score of 99 with "Max Potential First Input Delay" of 170ms

Now, that's better! Still a bit disheartening considering the simplicity of the page (which you can find here) and the fact that a few months ago this result was considerably better. As Lighthouse is changing its metrics and weight attributes over time (see the weights for V2 and compare them to the weights for V3), seemingly putting more emphasis on aspects that are highly affected by JS heavy set-ups, I expect Gatsby sites to perform worse and worse over time.

Anyway, it's still a good gain that becomes more expressive on bigger sites, and it comes at no cost / collateral, so switching to Preact is an obvious choice. I'm not sure if you'd hit incompatibilities on big apps that make use of other libraries such as Apollo, etc., but in my experience I haven't seen a single site with a problem so far. And to do it, the process is super straightforward and simple (alternatively, you can follow the plugin's official docs)!

npm i gatsby-plugin-preact preact

And then, in your gatsby-config.js:

/* ... */ plugins: [/* ... */ `gatsby-plugin-preact`];

There you go! 1 npm install and 1 line of code later, and you've saved 45.2% of uncompressed JS (43.02% for of the download size) 🎉🎉

Do yourself, and the internet / users / planet, a favor and do that for every Gatsby site you ever make! Heck, you can even bake it into your default base theme / starter, easy peasy!

Bonus tip: remove ALL Javascript 😈

Now, if you're building a simple website / blog that doesn't benefit from the SPA aspects of Gatsby and doesn't use any dynamic features of React, like my blog and many others I've seen out there, you don't need to cope with the tons of JS nor ditch Gatsby's data layer and templating niceties... you can remove all Javascript from your site!

This one is obviously not for every situation, but can make absolute sense if the average user of the site is not going to navigate to tens of pages and always come back, case in which having Gatsby's caching and service worker capabilities would be great. However, I'm more than happy to do this tradeoff on my own blog, and here are the results:

Screenshot of the Network tab with only 17.7kb being transferred in total
Screenshot of the Network tab with only 17.7kb being transferred in total

Lighthouse result of 100 with "Max Potential First Input Delay" of 20ms. My site is now faster than 99% of the whole web 🥳
Lighthouse result of 100 with "Max Potential First Input Delay" of 20ms. My site is now faster than 99% of the whole web 🥳

They speak to themselves, but they could be even better if the gatsby-plugin-no-javascript - which I used to remove JS from the site - also removed the page-data.json file, which increases my payload by 70,2% for no reason, as it only makes sense in the context of hydrating the app.

This is achieved with a simple yarn add gatsby-plugin-no-javascript and adding the following to your gatsby-config.js:

/* ... */ plugins: [/* ... */ `gatsby-plugin-no-javascript`];

⚠ Note: plugins related to your hosting provider - specifically, I ran into it with Netlify - can add some specific headers to you requests that point to JS files. Make sure to delete them to avoid this behavior 😉

In conclusion, Users will now save more of their bandwidth, load your site faster and feel less the effects of JS bloat (high input delay, janky scrolling, etc.). As web devs, we must be more and more vigilant to the impacts of our choices for businesses and users. Serving unnecessary JS might be comfortable for us, but it's bad for everyone, even the planet (think about the bandwidth, and consequent electric energy, being wasted on the internet!). We can't blind our sights to this in name of UX!


Written by Henrique Cavalieri

Find me on: