Hooray you’re back!
This is just a quick post to help you on your way with optimum web performance.
There’s many things that can trip us up along the stoney path of web development and one that I see a lot is, Fonts.
Seems silly right? We’ve been able to add custom fonts to websites since approximately 1998 when CSS2 introduced the @font-face rule.
But as is the way with modern website development the “easy” approach might not be the “best” approach.
One such “easy” approach is using https://fonts.google.com/. If you use either the <link>
or @import
method your website will make a request to the Google servers to download font files or CSS.
A similar “easy” approach is using gatsby-plugin-google-fonts, but the same issues mentioned above still apply.
It goes without saying that Google’s servers are fast, but no matter how you spin it, to load fonts into your site your browser will have to make a separate HTTP Request to “fetch” these fonts from Google’s servers before your website site looks as it should.
Here’s a breakdown of some of the steps involved when making an HTTP request which should help you understand the problem.
- DNS Lookup: The client tries to resolve the domain name for the request.
- Connect: Client establishes TCP connection (verify ssl) with the IP address of hostname.com
- Send: Client sends the HTTP request to the web server.
- Wait: Client waits for the server to respond to the request.
The above steps take time, time that’s crucial when optimizing for performance, and naturally, the less time it takes for your site to finish loading all of the required resources, the better the experience is for your users.
As a result, requesting font files from a remote location such as https://fonts.google.com/ commonly increases LCP (Largest Contentful Paint). This metric is used by Lighthouse to determine when the largest visible area of your site is available to the end user. Larger time (in seconds) leads to poorer overall performance scores.
Using methods outlined in this post I’ll be demonstrating how to add custom fonts to a Gatsby site in a more performant way.
If you’re keen to jump ahead I’ve prepared a demo repo with a pull request that shows the diff plus x2 Gatsby Cloud preview URLs.
With the following links you’ll be able to see the different methods.
- Demo w/Plugin: https://gatsbycustomfonts.gatsbyjs.io/
- Repo w/Plugin: https://github.com/PaulieScanlon/gatsby-custom-fonts
- Demo w/Local Fonts: https://gatsbycustomfonts-featlocalfonts67723.gtsb.io/
- Repo w/Local Fonts PR: https://github.com/PaulieScanlon/gatsby-custom-fonts/pull/3/files
The Impact of Google Fonts on Site Performance
I mentioned above that using Google Fonts requires the browser to make a “separate HTTP Request”, and to help visualize this and to provide a little more information about why this can negatively impact you site’s performance here’s an EcoPing report showing the resource breakdown by location for the Demo w/Plugin referenced above.
The resources coming from 🇮🇹 are Gatsby’s essential JavaScript and HTML served from Gatsby Cloud, and the resources coming from 🇬🇧 are Google Fonts’ Font files, Javascript and CSS.
Using Gatsby Clouds’s built-in Lighthouse reports you can see what effect this has on the Performance score – Yikes!
Improve Site Performance Using Local Fonts
A semi-quick win here is to load all fonts from the same location. You can achieve this by removing the Google fonts plugin and adding the actual font files to your Gatsby project.
Here’s how 👇.
Remove The Plugin
Uninstall gatsby-plugin-google-fonts
and remove the reference to it in gatsby-config.js
Add Link tags to HTML Head
There’s a few things going on here so i’ll explain.
onRenderBody
onRenderBody is one of gatsby-ssr
’s extension points and runs after each page is created by Gatsby. It can be used to set HTML <head />
or <body />
elements.
To set <link />
tags in the HTML <head />
you can use the setHeadComponents
function.
One <link />
attribute I’d like to draw your attention to is rel="preload"
. This tells the browser: “HEY, THIS IS IMPORTANT”. Whilst this may not improve actual loading time, they do reduce the time that unstyled content is shown (FOUT).
You can read more about the HTML Link element attributes on MDN: <link>: The External Resource Link element.
@font-face
It’s a little hard for me to explain where in your Gatsby site you’d need to add the @font-face
declarations since this will be determined by how you’re using CSS. In my demo i’ve created a global.css file which is imported by gatsby-browser.js.
Oh and just a note to say I’m only using the .woff2
for demo purposes, it’s more common in production sites to use both .woff
and .woff2
. You can read more about font format support here: https://caniuse.com/woff2
Font Files
Lastly you’ll need to add the actual font files to Gatsby’s static
directory. Files contained within this directory are moved to the public
directory once Gatsby has completed the build.
In my demo I’ve created a fonts directory in static, E.g static/fonts
.
The Impact of Local Fonts on Site Performance
I ran the PR branch through EcoPing to see what the resource locations now look like – Better!
You might notice that even though “technically” the Font metric has increased from the Google Fonts version, all the resources are now coming from the same location.
This results in a much better looking Lighthouse report.
In web development there’s usually always a trade off for the “easiest” vs the “fastest” or the “best” approach and manual optimizations like this do often take a little more time but I hope you’ll agree with me, slow and steady wins the race – I learnt that from the Tortoise 🐢.
Ttfn friends.
Paul 🕺