How to preload fonts on Netlify (issue resolution)

How to preload fonts on Netlify (issue resolution)

On my personal website, I am preloading the fonts to improve page loading speed and to prevent FOUT (Flash of unstyled text). I had noticed that FOUT was still happening sometimes on slower connections and wasn’t sure why. When I ran a performance audit of my homepage on WebPageTest, I saw in the Opportunities & Experiments section that my fonts were not being preloaded! Strange! 😕

WebPageTest lists 2 opportunities related to this issue:

  1. 2 fonts are hosted on 3rd-party hosts
  2. 2 resources are being preloaded, but are not used during page load.

When I drilled into the first item, I saw that the domain of my fonts is cloudfront.net. I host my website on Netlify and have my fonts there too. It appears that Netlify moves my font files to another domain and rewrites some of the URLs in the head of the webpages when it builds my website.

Opportunities & Experiments item: 2 fonts are hosted on 3rd-party hosts. It shows the 2 URLs which are

Inspecting my home page in production, the head looks as follows:

<head> 

<link rel="preload" href="/assets/fonts/nunito-regular-webfont.woff2"
as="font" type="font/woff2" crossorigin="">


<style>
@font-face{
font-family:Nunito;
src :url("https://d33wubrfki0l68.cloudfront.net/bd0f31921c6187f994fbf2b3b22f74a0f3e87b2e/fd58e/assets/fonts/nunito-regular-webfont.woff2") format("woff2");
font-display:swap
}
</style>

<!-- other stuff -->

</head>

As you can see, the URL in the link and the @font-face rule do not match. In my source code, they match! Therefore, Netlify has rewritten the URL in the @font-face rule. How can I get Netlify not to do this? 😅

The solution to stop Netlify hosting a font file on a 3rd party domain

Someone else posted a very similiar question – Asset optimization - preloading fonts – on this topic on the Netlify Support forum. The Netlify staff say the following:

The cloudfront URL’s are the result of asset optimization, as configured on your site’s deploy settings page most of the way down.

Things that get optimized (which don’t include the tag at present) will get rewritten to cloudfront URL’s. HOWEVER all content we serve is served from a CDN - that’s just the CDN we use for optimized assets. All traffic from netlify comes from some part of some CDN

If you want things to be consistent, turn off that feature in our UI. But hopefully things work normally, even if they look a little weird in the source code?

The issue is that asset optimization rewrites URLs and they do not include the link tag. In the same thread, the support staff member stated that Netlify do not intend to change this behaviour!

The suggested solution is to disable asset optimization (post processing) completely. However, I want to use some facets of asset optimization e.g. minifying JavaScript. Therefore, I would prefer not to disable it.

Instead, I changed my page template to produce absolute URLs in the link and the @font-face rule and it solved the issue!

I use nunjucks for my page template, and have a custom filter toAbsoluteUrl for this task. This is what it looks like if you happen to use nunjucks:

{% set regularFont = "/assets/fonts/nunito-regular-webfont.woff2" | toAbsoluteUrl %}

<link rel="preload" href={{ regularFont }}
as="font" type="font/woff2" crossorigin/>

<style>
@font-face {
font-family: Nunito;
src: url({{ regularFont }}) format("woff2");
font-display: swap;
}
</style>

Rerunning the test on WebPageTest, I can see that now visual progress is 100% after 1.7 seconds and there is no cumulative layout shift (blue line in graph). Previously it took 2.4 seconds and there was a very minor cumulative layout shift (red line in graph)! 📈

Graph comparing visual progress metric between 2 runs on WebPageTest. The second run is after I fix the URL issue. You can see that now visual progress is 100% after 1.7 seconds, previously it took 2.4 seconds

That may not sound like much, but it mitigates FOUT significantly!

Tagged