SkateSpots/src/lib/cjkFonts.ts
SkateSpots cc250b4d0b perf(fonts): lazy-load CJK fonts per locale (~16MB font payload off the boot path)
Kanit (th), Noto Sans JP (ja) and Noto Sans KR (ko) were imported statically in main.tsx, so every visitor downloaded ~16MB of CJK font files. They're now loaded on demand once per locale (lib/cjkFonts.ts, wired in LanguageContext), so non-CJK users never fetch them and CJK users get their font after the first paint.
2026-10-12 19:52:54 +07:00

38 lines
1.3 KiB
TypeScript

import type { Language } from '@/contexts/language';
const loaded = new Set<Language>();
/**
* Lazy-load the CJK display font for the active locale.
*
* The Thai (Kanit), Japanese (Noto Sans JP) and Korean (Noto Sans KR) font
* families are large and only needed for users on those locales — but they were
* imported statically in main.tsx, so every visitor downloaded them. They are
* now loaded on demand, once per locale, and non-CJK users never fetch them.
* Text briefly falls back to a system font until the stylesheet resolves.
*/
export function loadCjkFont(language: Language): void {
if (loaded.has(language)) return;
loaded.add(language);
if (language === 'ja') {
void Promise.all([
import('@fontsource/noto-sans-jp/400.css'),
import('@fontsource/noto-sans-jp/500.css'),
import('@fontsource/noto-sans-jp/700.css'),
]).catch(() => {});
} else if (language === 'ko') {
void Promise.all([
import('@fontsource/noto-sans-kr/400.css'),
import('@fontsource/noto-sans-kr/500.css'),
import('@fontsource/noto-sans-kr/700.css'),
]).catch(() => {});
} else if (language === 'th') {
void Promise.all([
import('@fontsource/kanit/400.css'),
import('@fontsource/kanit/500.css'),
import('@fontsource/kanit/600.css'),
import('@fontsource/kanit/700.css'),
]).catch(() => {});
}
}