Improving my website's performance (Part - 2) - Font Optimizations

8 min read
📝 1246 words
Improving my website's performance (Part - 2) - Font Optimizations

Current State (Aug 1, 2025)

So in the last part we fixed the image optimizations, You can check the Part - 1

So the performance had been good after that, which resulted in scoring 100 for performance in Lighthouse for Desktop view.

July 30 Performance Lighthouse

In this article, we gonna optimize our font loading performance.

Issue 3 - Font is loading a bit slow

Analysis

As I pulled up the HAR Tool reports for my site, I found the size of the font was causing a slow load time

HAR Analysis 1

Digging deep, I found that the size of the font was around 49KB around

HAR Analysis 2

And pulling up the Chrome Devtools Performance Insights, it was taking around 20ms to load in my network. As you can see in the below image for font file (.woff2)

Dev tools Performance Analysis

The Font Loading Dilemma 🤔

Let's be honest — we've all felt that moment of irritation when a website's text suddenly shifts or appears out of nowhere. As developers, we're caught in a painful dilemma: beautiful typography that risks annoying users with performance issues, or basic system fonts that load instantly but lack personality.

These font loading issues aren't just technical problems — they create real emotional responses in our users:

  1. Flash of Invisible Text (FOIT): That maddening moment when you can see the site but not read anything.

  2. Flash of Unstyled Text (FOUT): The jarring experience when text suddenly changes appearance.

  3. Layout shifts: The infuriating feeling when you're about to click something and it moves.

  4. Slow loading: The frustration of waiting for content that should be immediate.

I've experienced the pain of these issues firsthand, both as a developer and as a user.

Loading Font's in Nextjs

So I have been using the next/font with Google Font Alexandria, though it uses disk cache and doen't make api calls everytime, I wanted a better speed for the font to be loaded.

With React

Whenever I use google font's i usually used to preconnect them, if it's a react project in head

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Alexandria:wght@100..900&display=swap" rel="stylesheet">

and then I used to use that in styles:

.alexandria-<uniquifier> {
  font-family: "Alexandria", sans-serif;
  font-optical-sizing: auto;
  font-weight: <weight>;
  font-style: normal;
}

With this approach, it gave a good font loading experience.

With Next.js

But for Nextjs, Earlier I was using this approach for using the font.

import { Alexandria } from "next/font/google"

const alexandria = Alexandria({
  weight: "400",
  subsets: ["latin"],
})

return (
 <html lang="en" suppressHydrationWarning>
      <head>
        <link rel="icon" href="/favicon.ico" />
      </head>
      <body
        className={`${alexandria.className} `}
      >
         Body goes here
      </body>
 </html>
);

But then i read this NextJs Font Optimization article

Switching to Local Font's - Better UX

Local Font's are performant because it reduces the network call to the google font cdn, inturn reducing the extra network call to fetch font (reducing the load time and thus improving the user experience)

Steps to switch to local font

  1. Download the font from Google Fonts

You need to download the ttf format for the variable Fonts

Downloading Alexandria Google Font

After Downloading, you can read this article on Self Hosting Web Fonts

Using Alexandria Google Font Locally Docs

After downloading you will find both static and variable fonts

Font - Alexandria

Converting TTF fonts to Woff2 format

So why not TTF ?

TTF (TrueType Font) and WOFF2 (Web Open Font Format 2) are both font file formats, but WOFF2 is generally preferred for web use due to its superior compression and smaller file sizes, which lead to faster website loading times. While TTF is widely compatible, its larger file sizes can negatively impact performance, especially on slower networks.

**Here's a more detailed comparison: **

TTF (TrueType Font):

Compatibility: Widely supported across different operating systems and browsers, including older ones.

File Size: Generally larger than WOFF2, which can lead to slower website loading.

Use Cases: Suitable for situations where broader compatibility is crucial, especially when supporting legacy systems.

WOFF2 (Web Open Font Format 2):

Compatibility: Supported by modern browsers like Chrome, Firefox, Safari, and Edge.

File Size: Significantly smaller than TTF due to its advanced compression, resulting in faster page load times.

Use Cases: Ideal for web use, especially when prioritizing website performance and faster loading.

Key Differences:

Compression:

WOFF2 uses Brotli compression, which is more efficient than the compression used in TTF. Performance:

WOFF2's smaller file size translates to faster website loading and improved user experience. Support:

While TTF has broader compatibility, WOFF2 is the recommended format for modern web browsers.

Recommendation:

For optimal web performance, it's generally recommended to use WOFF2 as the primary font format and include TTF for legacy browser support if needed. You can also consider using a font converter to create both formats from a single source font file.

Use a TTF to WOFF2 Online/Offline Convertor Tool

For my case, I used CloudConvert TTF to Woff2 tool

TTF to Woff2 OnlineConvertor

Compressing the Woff2 Font :

  1. First, install fonttools using pip (make sure you have Python installed):
$ brew install python3
$ pip3 install fonttools brotli zopfli
$ which pyftsubset

If it's still not found, you might need to add Python's bin directory to your PATH. Add this to your ~/.zshrc:

Reload your shell

$ source ~/.zshrc
  1. Then you can minify the WOFF2 font using this command in your terminal:

This will generate a new subset font in compressed woff2 format

You need pyftsubset

$ cd /your-project/public/fonts

$ pyftsubset "Alexandria-VariableFont_wght.woff2"
 --output-file=Alexandria-subset.woff2 
 --flavor="woff2" \
 --layout-features='*' \
 --unicodes="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD"
  1. To verify the file size reduction:

Run the following command, to size the file size difference :

$ ls -lh Alexandria-VariableFont_wght.woff2 Alexandria-subset.woff2

In my case, it reduced from 123KB to 45KB !!

  1. Then we can link the new subset woff2 file in the code using
// import { Alexandria } from "next/font/google"Add a comment on line R2Add diff commentMarkdown input: edit mode selected.WritePreviewAdd a suggestionHeadingBoldItalicQuoteCodeLinkUnordered listNumbered listTask listMentionReferenceSaved repliesAdd FilesPaste, drop, or click to add filesCancelCommentStart a reviewReturn to code
import localFont from "next/font/local";

// const alexandria = Alexandria({
//   weight: "400",
//   subsets: ["latin"],
// })

const alexandria = localFont({
  src: "../../public/fonts/Alexandria-subset.woff2",
  display: 'swap',
  preload: true,
  fallback: ['system-ui', 'arial'],
  variable: '--font-alexandria', // Add this if you want to use CSS variables
});

// ...existing code...

Performance (After changes)

So now after measuring the new performance, there is a significant change in the performance based on the tools, as you can see below

Network Loading Performance after changes for font loading

The new loading speed was around 6ms compared to earlier which was 20ms (almost 14ms difference).

HAR Performance after changes for font loading

The new size of the font fetching was around 44KB as compared to earlier which was 128KB (almost 84K difference)

And the overall light house performance was almost the same in greens.

Lighthouse Performance after changes for font loading

Yayee ! More perf upgrades to come.

Hope you like this article, and the new site performance.

Font Loading Performance

| Metric           | Before (Google Fonts) | After (Self Hosting) | 
| ---------------- | --------------------- | -------------------- |
| Font File Size   | 128KB                 | 44K                  |
| Loading Speed    | 20 ms                 | 6ms                  |

Thanks for visiting.