Reputation: 2520
I use custom fonts on a website. It works, but it looks like they aren't cached long enough, as I way too often get FOUT. Some times multiple times a day, on production. I'm hoping I can cache fonts for a longer period (or another solution) to prevent this from occurring as often.
Fonts are preloaded in _document.tsx
like this:
<link
rel='preload'
as='font'
href='/fonts/Calibre-Regular.woff2'
type='font/woff2'
crossOrigin='anonymous'
/>
Then in _app.tsx
like this:
<script jsx>{`
@font-face {
font-family: 'Calibre';
font-display: swap;
src: url('/fonts/Calibre-Regular.woff2') format('woff2'),
url('/fonts/Calibre-Regular.woff') format('woff');
}
`}</script>
How can I improve this? Or set a longer cache time for the fonts? 🙏🏻
Upvotes: 5
Views: 5903
Reputation: 57408
I wouldn't be so sure that FOUTs are caused by the fonts not being cached long enough. Could they be not yet loaded, for example? The preload
link should cause the browser to request the font and cache it normally - the WOFF(2) files are static files anyway. Unless special pains are taken to not cache them, they should be cached and stay cached.
So, I would first of all check the request and response headers for those WOFF files, both from the client and the server. What is it exactly that gets sent to the Vercel layer? And, more important, what is it that gets sent from the server to the cache? (I have misplaced enough cache-related pragmas myself that I now always check those first).
If that is OK, and I wouldn't bet on that, I would look at the actual load times and request waterfall from the site during a FOUT. This might point to caching problems or errors in the load sequence (much more rarely, but I have my share of those too).
If nothing shows out at this point, you could try to get rid of FOUTs otherwise - load animations, load delay, or just hiding the text.
But my money is on the server-Vercel leg of the journey, 70% on the server sending borked headers, 30% on Vercel not reacting properly.
A dirty and terrible way to be sure whether it is the cache or something else is to have another machine prod the cache continuously at appropriate intervals from the same network (e.g. a cron job, or even more brutal, a while
loop with curl
and sleep
from a terminal on a commodity Raspberry), at a frequence higher than that of the FOUT occurrences. If that makes the FOUTs disappear, then it might really be the caching time -- but frankly, I'd be really surprised.
Upvotes: 0
Reputation: 2150
Without seeing the full example, I’d:
link
tag and script
(which should be a style
tag?) should be part of the initial HTML<link />
tag and separate CSS style that, which only contains the @font-face
declarations. Yes, this adds one additional HTTP request, but then that CSS would presumably follow Vercel’s static caching rules and not change for 31 days: https://vercel.com/docs/edge-network/caching#static-files (although it’s unclear here whether the cache is invalidated when you redeploy that file, or when you do any deploy)For example, to cache everything in the fonts/
directory for one week (and assuming the new, external CSS file is there as well), the config would be:
{
"routes": [
{
"src": "/fonts/(.*)",
"headers": { "cache-control": "s-maxage=604800" },
"dest": "/fonts/$1"
}
]
}
This is based on the config example in the docs: https://vercel.com/docs/configuration#routes/headers
Hope one or more of those together is helpful!
Upvotes: 3