Open arvl130 opened 1 year ago
Kind of disappointing to see no activity here after more than six months of being reported. To anyone else facing this issue, here is the workaround I'm using.
I found that the normal way of importing fonts (with @import
) from Google Fonts doesn't cause any flickering. So during development, that's the method I use to load my fonts. I only use next/font
in production.
You can conditionally change the way you load fonts by creating a Fonts
component like this:
"use client"
import { Inter } from "next/font/google"
import { useServerInsertedHTML } from "next/navigation"
const inter = Inter({
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
display: "swap",
})
export function Fonts() {
useServerInsertedHTML(() => {
// Load fonts with @import during development due to a `next/font` bug.
// For more info, see: https://github.com/vercel/next.js/issues/52159
if (process.env.NODE_ENV === "development")
return (
<style
dangerouslySetInnerHTML={{
__html: `
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
`,
}}
/>
)
return (
<style
dangerouslySetInnerHTML={{
__html: `
:root {
--font-inter: ${inter.style.fontFamily};
}
`,
}}
/>
)
})
return <></>
}
Remove next/font
from your root layout. Then, import your Fonts
component above the HTML <body>
element:
import type { Metadata } from "next"
import "./globals.css"
import { Fonts } from "./fonts"
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<Fonts />
<body>{children}</body>
</html>
)
}
In my projects, I typically register my default sans font in font-sans
. If you're doing something similar, make sure to conditionally register your fonts in there as well.
import type { Config } from "tailwindcss"
import { fontFamily } from "tailwindcss/defaultTheme"
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
fontFamily: {
sans: [
process.env.NODE_ENV === "development"
? "Inter"
: "var(--font-inter)",
...fontFamily.sans,
],
},
},
},
plugins: [],
}
export default config
Hopefully, we can get more attention from the Next.js Team in the near feature. This issue isn't particularly hard to reproduce. It's a very obvious bug when developing with Firefox.
Small update: Starting in Next.js version 14.x, it looks like this issue won't appear if you use Turbopack in development.
Verify canary release
Provide environment information
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true), Font optimization (next/font)
Link to the code that reproduces this issue or a replay of the bug
https://github.com/arvl130/nextjs-bug-repro-flicker-on-hmr
To Reproduce
Run the dev server in a terminal and open the homepage in Firefox. Wait for the page to fully load.
Once the page has loaded, open another terminal and run the helper script included in the repository:
Describe the Bug
If you use
next/font
on your Next.js app, during development, all text on your page will briefly disappear whenever HMR is triggered. This does not happen with the Pages dir. It also does not happen when developing with Chrome.https://github.com/vercel/next.js/assets/59502616/681849c8-d44d-443d-bedf-f6c92f08698d
I can reproduce the issue on both Windows and Linux.
Expected Behavior
Text should not flicker when HMR is triggered, like in the Pages dir.
Which browser are you using? (if relevant)
Firefox 114.0.2
How are you deploying your application? (if relevant)
No response