Next.js Discord

Discord Forum

Most efficient way to handle LOTS of fonts to build a sort of “Google fonts playground”?

Answered
LuisLl posted this in #help-forum
Open in Discord
I know next-font package is basically a wrapper for getting font from the Google Fonts repository, but I’m not sure it’s the most performant solution to load 40-60 fonts. Should I import and instance all the fonts at the same time with the next-font api?

Or what are your suggestions to load that many fonts?
Answered by LuisLl
I ditched the next/font package approach completely and I ended doing this instead:
I dynamically loaded the needed font for the 3 variants.
- If user never changed font, fonts will only load for the initial ones
- If user changes fonts this will trigger a fetch for that specific font while maintaining the previuos ones cached in the browser, so no extra fetches thanks to the browser default behavior
- React will automatically place the link tags in the head and sync the current fonts
View full answer

4 Replies

@LuisLl I know `next-font` package is basically a wrapper for getting font from the Google Fonts repository, but I’m not sure it’s the most performant solution to load 40-60 fonts. Should I import and instance all the fonts at the same time with the next-font api? Or what are your suggestions to load that many fonts?
the suggestion is to not load that many font. only load the font when it is needed (font entry enters view for example)

you may also want to subset the font (generate a smaller font file containing only the glyphs you need) – this is helpful when e.g. you don't need to support custom font previews and only need the font to support few characters like in a font selector
@joulev the suggestion is to *not* load that many font. only load the font when it is needed (font entry enters view for example) you may also want to subset the font (generate a smaller font file containing only the glyphs you need) – this is helpful when e.g. you don't need to support custom font previews and only need the font to support few characters like in a font selector
I ditched the next/font package approach completely and I ended doing this instead:
I dynamically loaded the needed font for the 3 variants.
- If user never changed font, fonts will only load for the initial ones
- If user changes fonts this will trigger a fetch for that specific font while maintaining the previuos ones cached in the browser, so no extra fetches thanks to the browser default behavior
- React will automatically place the link tags in the head and sync the current fonts
Answer
So I had this fonts object (one for each sans, serif and mono) already to map my fonts in the UI, so I added the href property and that's the href I pass to <link href={monoFontHref} /> dynamically.

export const monoFonts = {
  "Geist Mono": {
    key: "Geist Mono",
    value: "Geist Mono, monospace",
    href: "https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500;600;700&display=swap",
  },
  "JetBrains Mono": {
    key: "JetBrains Mono",
    value: "JetBrains Mono, monospace",
    href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap",
  },
  "Fira Code": {
    key: "Fira Code",
    value: "Fira Code, monospace",
    href: "https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&display=swap",
  },
  "IBM Plex Mono": {
    key: "IBM Plex Mono",
    value: "IBM Plex Mono, monospace",
    href: "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&display=swap",
  },
  "Source Code Pro": {
    key: "Source Code Pro",
    value: "Source Code Pro, monospace",
    href: "https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;500;600;700&display=swap",
  },
  "Space Mono": {
    key: "Space Mono",
    value: "Space Mono, monospace",
    href: "https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;500;600;700&display=swap",
  },
} as const;

export const monoFontsArray = Object.values(monoFonts); // I use this to map and display the fonts in the UI
Before / After on initial page load. The difference is CRAZY