How to Prevent Duplicate Font Loading in Next.js?

In Next.js, when you call the localFont or Google font function multiple times for the same font in different parts of your application, it is loaded again and again, like it's a new copy each time. To demonstrate this, consider the following two components that each call the Google font function:

// components/Heading.jsx
'use client'

import { Inconsolata } from 'next/font/google';

const inconsolata = Inconsolata();

const Heading = ({ children }) => (
  <h1 className={inconsolata.className}>
    {children}
  </h1>
);

export default Heading;
// components/Text.jsx
'use client'

import { Inconsolata } from 'next/font/google';

const inconsolata = Inconsolata();

const Text = ({ children }) => (
  <p className={inconsolata.className}>
    {children}
  </p>
);

export default Text;

When you use these components in your application, it will load the same font twice:

// app/page.js
import Heading from '@/components/Heading';
import Text from '@/components/Text';

export default function Page() {
  return (
    <article>
      <Heading>foo</Heading>
      <Text>bar</Text>
    </article>
  )
};

However, you can optimize this behavior to only load the font once by:

  1. Creating a "font definition" file in which you load the font only once and export the corresponding font object;
  2. Importing the font object (from the font definition file) wherever you need to use the font.

For example, you can create a "fonts.js" file in a "styles" folder at the root of your application directory:

// styles/fonts.js
import { Inconsolata } from 'next/font/google';
// import localFont from 'next/font/local';

const inconsolata = Inconsolata();
// const customFont = localFont({ src: './MyFont-Regular.ttf' });

export { inconsolata/*, customFont */ };

Once you've defined your fonts in a central place, you can use them in your code, for example, in the following way:

// components/Heading.jsx
'use client'

import { inconsolata } from '@/styles/fonts';

const Heading = ({ children }) => (
  <h1 className={inconsolata.className}>
    {children}
  </h1>
);

export default Heading;
// components/Text.jsx
'use client'

import { inconsolata } from '@/styles/fonts';

const Text = ({ children }) => (
  <p className={inconsolata.className}>
    {children}
  </p>
);

export default Text;

Not only will this help you load the font once, but also with organizing your application fonts in a central location.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.