This article was originally published at zsgomori.dev. Head over there if you like this post and want to read others like it!
Font optimisation techniques, such as pre-loading, not only can contribute to more efficient Core Web Vitals scores, but also can help prevent your visitors from experiencing FOUT and FOIT. Our today’s topic will focus on HTTP Cache and how to utilise it to cache self-hosted fonts on Netlify.
We will start off with a brief brush up on how HTTP Cache works and what doors it unlocks. Then, I’ll walk you through the steps I followed to cache my fonts on this website.
TL;DR
For those of you who want to cut to the chase, copy-paste the snippet into your netlify.toml
configuration file:
[[headers]]
for = "/fonts/*"
[headers.values]
cache-control = '''
max-age=365000000,
public
immutable'''
You may need to vary either the route or the cache-control values — or even both! - to suit your particular needs.
How Does HTTP Cache Work?
- When the browser encounters a request to an asset while parsing your HTML's metadata, it checks whether there’s already a valid cache response in its cache, before reaching out to the web server.
- If there’s no cache that would fulfill the request or the cache is stale, the request gets forwarded to the web server.
- The web server processes the request and acts accordingly — it sends the requested asset back over the wire. Besides, if configured, it augments the response headers with
Cache-Control
to specify the directives for caching mechanisms (for example, for how long the cache will be considered fresh).
In a nutshell, that’s it. One of the major benefits of caching is that on subsequent requests to the same asset, the browser does not need to carry out the transmission of the request towards the server over and over again.
Instead, so long as the cached response’s lifetime has not expired yet, the browser will intercept the request and reuse the previously cached response to fulfill it. Consequently, we are gaining on speed by reducing the roundtrips between the browser and the server.
Explaining the ins and outs of the HTTP Cache flow, making sure of cache freshness with ETag and Last-Modified in particular, is beyond the scope of this article. If you’re looking for an in-depth explanation, consult with the MDN docs.
Caching Fonts on Netlify
We have already touched on the configuration part — it’s as straightforward as adding an additional header to outgoing responses. When it comes to Netlify, hooking into and altering their default caching behaviour is literally a piece-of-cake-task.
It should be fairly straightforward even if you use a different platform (e.g. Vercel) or run your web server on your own.
For the sake of completeness, here’s the exact same snippet from the TL;DR section:
[[headers]]
for = "/fonts/*"
[headers.values]
cache-control = '''
max-age=365000000,
public
immutable'''
In addition to the file-based configuration approach, you can also define caching policies in the
_headers
file.
If TOML is somewhat confusing, the JSON equivalent may help better grasp what's going on:
{
headers: [
{
for: "/fonts/*",
values: {
"cache-control": "max-age=365000000,public,immutable"
}
}
]
}
Let me briefly expand upon what’s happening here.
The for
keyword declares the path or URL which the headers will be added to. In my case, I self-host my fonts and they live inside the static/fonts
folder, which ultimately will be exposed via the /fonts
route. Therefore, the following link pointing to the Poppins font on my site will match the /fonts/*
pattern:
<link
rel="preload"
href="/fonts/Poppins-Regular.woff2"
as="font"
type="font/woff2"
crossorigin="anonymous"
/>
Onto the values
keyword. As the name suggests, here you can tie the header values up to the route it’s grouped under. The max-age=<seconds>
directive dictates the lifetime of a resource, that is, the maximum amount of time a resource is considered fresh. Given that the fonts on my site are quite unlikely to change in the foreseeable future, I store them for more than a year.
You can learn more about the available set of directives on MDN.
And that's a wrap, folks!
Thanks for reading the article! I genuinely hope you learned something new! Feel free to leave a comment or hit me up on Twitter with any questions.
Top comments (0)