Greetings Stack Overflow community! I'm using some custom fonts in my Next.js project using the following CSS:
@font-face {
font-family: OpenSans;
font-display: swap;
src: url(./OpenSans-Regular.woff2) format('woff2');
}
The thing is that Lighthouse audit it's telling me to preload these .woff2
files but they are getting hashed by Next.js. I don't know how to add the link
tag with rel="preload"
for the fonts.
Where can I tell Next.js to preload these fonts?
Thanks you!
I had the same issue, but this article gave the correct solution
Problem is, the font files get compiled if you place them in any other folder besides public. So if you place them in the public folder and reference them manually, you can be using the link preload like below.
Include them in the Head tag and specify the type for the different font types for browser compatibility. Make sure to reference them correctly in the css as well.
<Head>
<link
rel="preload"
href="/fonts/yourfont/yourfont.woff2"
as="font"
crossOrigin=""
type="font/woff2"
/>
</Head>
@font-face {
font-family: "YourFont";
font-style: normal;
font-weight: 900;
src: url('/fonts/yourfont.woff2') format("woff2"),
url('/fonts/yourfont.woff') format("woff"),
url('/fonts/yourfont.ttf') format("truetype"),
url('/fonts/yourfont.svg#yourfont') format("svg");
}
For external fonts, you can simply add the preload link in your head component;
<link rel="preload" href="https://fonts.googleapis.com/css?family=Play&display=swap" as="font" />
As for the internal fonts that you have in your public
folder, this requires;
file-loader
configuration in next.config.js
, this is to resolve the hashed filenameWhich you can find my sample below;
I created a Layout.tsx
which wraps my other components, which its main purpose is that there would not be duplicated meta tags - But this is unrelated to the question.
Here's the code I have in [email protected]
- to preload both external and internal fonts.
App.tsx
function App({ Component, pageProps }: AppProps): JSX.Element {
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<Provider store={store}>
<main className="main-container position-relative" data-testid="main-container">
<HeaderComp />
<Layout>
<Component {...pageProps} />
</Layout>
<FooterComp />
<ScrollToTop />
</main>
</Provider>
</Hydrate>
</QueryClientProvider>
);
}
Layout.tsx
import fontGilroyBold from "@assets/fonts/gilroy/Gilroy-Bold.woff";
const Layout: React.FunctionComponent = ({ children }) => {
return (
<div className="content font-play position-relative">
<Head> {* next/head *}
{/* ...metaTags */}
<link rel="preload" href={fontGilroyBold} as="font" />
<link rel="preload" href="https://fonts.googleapis.com/css?family=Play&display=swap" as="font" />
</Head>
{children}
</div>
);
};
next-env.d.ts
...
declare module "*.woff";
declare module "*.woff2";
...
next.config.js
const nextConfig = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
/**
* Override some of the existing loaders
*/
// ...
/**
* Font imports in the code repository will be resolved as relative path
*/
config.module.rules.push({
test: /gilroy\/.+\.(woff|woff2)$/,
use: {
loader: "file-loader",
options: {
/** Stolen configuration from pre-existing "config.module.rules[2]" */
outputPath: "static/fonts/gilroy/",
publicPath: "/_next/static/fonts/gilroy/",
limit: 1,
},
},
});
return config;
},
};
You can preload them in your _document.js
inside the <Head>
component by adding the following:
<link
rel="preload"
href="/fonts/inter-var-latin.woff2"
as="font"
type="font/woff2"
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With