Preload fonts with Docusaurus (updated 03/11/2022)
John Reilly
December 29, 2021
When we're using custom fonts in our websites, it's good practice to preload the fonts to minimise the flash of unstyled text. This post shows how to achieve this with Docusaurus.
It does so by building a Docusaurus plugin which makes use of Satyendra Singh's excellent webpack-font-preload-plugin.
Updated 03/11/2022: Subsequently this post demonstrates how to achieve font preloading directly, by using the the headTags API.
Preload web fonts with Docusaurus
To quote the docs of the webpack-font-preload-plugin:
> The preload value of the element's rel attribute lets you declare fetch requests in the HTML's , specifying resources that your page will need very soon, which you want to start loading early in the page lifecycle, before browsers' main rendering machinery kicks in. This ensures they are available earlier and are less likely to block the page's render, improving performance.
>
> This plugin specifically targets fonts used with the application which are bundled using webpack. The plugin would add tags in the begining of of your html:
>
>
If you want to learn more about preloading web fonts, it's also worth reading this excellent article.
The blog you're reading is built with Docusaurus. Our mission: for the HTML our Docusaurus build pumps out to feature preload link elements. Something like this:
This link element has the rel="preload" attribute set, which triggers font preloading.
But the thing to take from the above text is that the filename features a hash in the name. This demonstrates that the font is being pumped through the Docusaurus build, which is powered by webpack. So we need some webpack whispering to get font preloading going.
Making a plugin
We're going to make a minimal Docusaurus plugin using webpack-font-preload-plugin. Let's add it to our project:
Now in the docusaurus.config.js we can create our minimal plugin:
It's a super simple plugin, it does nothing more than new up an instance of the webpack plugin, inside the context of the configureWebpack method. That's all that's required.
With this in place we're now seeing the elements being included in the HTML pumped out of our Docusaurus build. This means we have font preloading working:
Huzzah!
Using the headTags API
If you're using Docusaurus 2.2 or greater you can use the new headTags API and bypass using an extra dependency entirely.
To make this work, we need to ensure that our fonts live in the static directory which is reliably addressable - not hashed by webpack. We can then use the headTags API to add the link elements to the head of the HTML:
In our custom.css we need to add the following:
Note that the urls are fully qualified to prevent webpack from trying to bundle them. Another bonus of using the static folder is that we can apply long term caching. I'm using Azure Static Web Apps to run my site and so I'm achieving this with the following in staticwebapp.config.json:
Things to note from the above:
- Access-Control-Allow-Origin and Vary are in place to allow my staging sites to access the fonts from the production site. Without this, the fonts won't load in the staging site.
- The img and fonts directories sit under the static directory. For those directories we're going to use cache-control set to 6 months for the fonts and static images. They rarely change and so this is an appropriate strategy.
This blog post was migrated to the headTags API approach with the release of Docusaurus 2.2.0. You can see the PR here.
Discussion in the ATmosphere