Next.js App Font Not Loaded on Remote Machine Issue
Debugging note of a source loading issue that never reproduces on the dev machine.
June 5, 2023
TL;DR
@next/font config display: option will switch to fallback if the font takes more than 100ms to load. To ensure the font loading, use display: swap.
Issue
This blog is built in Next.js. When I first released it, there was an issue that the font only loads on my development machine. It reproduces on every remote machine, even if I access the dev server from the same wifi.
Configuration
I hosted my font using local .woff2 file, which I downloaded as .otf from google font then converted to .woff2 from the first converter I found on google.
The font file is loaded from a <link> element in _document.tsx.
When access either the dev server or the prod environment from the development machine, the font loads successfully. But when access from any other single machine on the world, the font won't load and the app switches back to default sans font.
The font file is successfully fetched on either machine, but on the remote machine the fetched font's content becomes the default sans font. I used some online .woff2 preview tool and it clearly shows that the downloaded .woff2 file is the default sans font. Such issue didn't happen on the development machine.
Attempts
I tried the configurations shown in this youtube video.
(It was super easy to understand, turns out it was a Vercel's developer's channel.)
I discarded the local .woff2 file and tried @next/font. Since I was using Tailwindcss, I set the font variable and the tainwind.config.js configurations.
After above configuration, the latin part of the font started to load on remote machine. Only the Japanese and Chinese parts remain the default sans font.
Root Cause
When creating font const using @next/font, the display option is defaulted to optional, which will switch to fallback font if the loading time is over 100ms.
Since I was using Noto Serif JP, the Japanese subset is way heavier than the latin set, which makes the Japanese part fallbacks to default font.
When I was hosting the .woff2 file instead of using @next/font, I didn't set the subset rules, hence made the whole font file too big to load, thus on every remote machine the font fallbacks. Only on the development machine, the font was not loaded through http but local disc, which it makes the below 100ms line.
Solution
Use display: swap to ensure font loading.
It causes some FOUT, but it's a way lesser evil compare to the origin issue.