Оптимизация кастомных шрифтов в Next.js с @next/font

Зачем оптимизировать шрифты
Коротко: нестабильная загрузка шрифтов замедляет первый рендер, вызывает «мигание» (FOIT/ FOUT) и ухудшает показатели Web Vitals. @next/font решает эти проблемы, поставляя шрифты локально и настраивая загрузку так, чтобы сократить задержки и избежать лишних сетевых обращений.
Важно: термины в одну строку
- FOIT — flash of invisible text, когда текст скрыт, пока шрифт не загружен.
- FOUT — flash of unstyled text, когда сначала показывается запасной шрифт, а затем — целевой.
Установка
Установите пакет через npm или yarn:
npm install @next/font
Или с yarn:
yarn add @next/font
Использование @next/font с Google Fonts
@next/font автоматически само-хостит Google Fonts на сервере Next.js — браузер не делает прямые запросы к Google. Это уменьшает количество внешних запросов и даёт больше контроля над загрузкой.
Пример импорта шрифта в файл _app.js (pages):
import { Roboto } from '@next/font/google'
const roboto = Roboto({ subsets: ['latin'] })
export default function MyApp({ Component, pageProps }) {
return (
)
}
Пояснения:
- subsets ограничивает набор символов (latin, cyrillic, greek и т.д.). Выбирайте поднабор, соответствующий языкам приложения.
- Можно указывать веса и стили: weight и style принимают массивы для нескольких вариантов.
Пример с несколькими весами и стилями:
const roboto = Roboto(
{
subsets: ['latin'],
weight: ['400', '500', '700'],
style: ['italic', 'normal']
}
)
Применение шрифта ко всему приложению через main:
import { Roboto } from '@next/font/google'
const roboto = Roboto(
{
subsets: ['latin'],
weight: ['400', '500', '600'],
style: ['italic', 'normal']
}
)
export default function MyApp({ Component, pageProps }) {
return (
)
}
Или применить только к отдельной странице:
import { Roboto } from '@next/font/google'
const roboto = Roboto(
{
subsets: ['latin'],
weight: ['400', '500', '600'],
style: ['italic', 'normal']
}
)
export default function Home() {
return (
Hello There!!!
)
}
Совет: ограничьте веса и поднаборы — каждый дополнительный файл шрифта увеличивает время загрузки.
Использование @next/font с локальными шрифтами
@next/font умеет оптимизировать локальные файлы шрифтов через localFont. Это полезно, когда вы храните WOFF2-файлы в репозитории.
Пример:
import localFont from '@next/font/local'
const myFont = localFont({ src: './my-font.woff2' })
export default function MyApp({ Component, pageProps }) {
return (
)
}
Мультифайловая конфигурация для одного семейства шрифтов:
const myFont = localFont(
{
src: [
{
path: './Roboto-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './Roboto-Italic.woff2',
weight: '400',
style: 'italic',
},
{
path: './Roboto-Bold.woff2',
weight: '700',
style: 'normal',
},
{
path: './Roboto-BoldItalic.woff2',
weight: '700',
style: 'italic',
},
]
}
)
Хорошая практика: используйте только WOFF2 и указывайте точные веса/стили, чтобы избежать генерации лишних @font-face.
Интеграция с Tailwind CSS
Чтобы использовать @next/font вместе с Tailwind, удобнее назначать шрифт через CSS-переменную и привязывать её к fontFamily в конфиге Tailwind.
Пример с Google-шрифтом Inter:
import { Inter } from '@next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
})
export default function MyApp({ Component, pageProps }) {
return (
)
}
Добавьте в tailwind.config.cjs:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./index.html",
"./src/**/*.{js,ts,jsx,tsx}",],
theme: {
extend: {
fontFamily: {
sans: ['var(--font-inter)'],
},
},
},
plugins: [],
}
После этого класс font-sans будет использовать ваш шрифт из CSS-переменной.
Рекомендации и лучшие практики
- Поднаборы: указывайте только нужные subsets (cyrillic/latin/greek). Это уменьшит размер загружаемых файлов.
- Веса: подключайте минимально необходимые веса. Чаще всего хватает 400/500/700.
- Формат: отдавайте предпочтение WOFF2 — он компактнее и поддерживается большинством браузеров.
- Критические стили: если важен первый рендер, используйте font-display: swap (по умолчанию @next/font обрабатывает это корректно).
- Preloading: @next/font управляет preload автоматически; не дублируйте вручную.
Отладка и распространённые ошибки
- Шрифт не применяется: проверьте className на main или контейнере, убедитесь, что переменная Tailwind корректно прописана.
- Дублирующиеся запросы к Google: возможно, где-то ещё подключён тот же шрифт через . Удалите лишние внешние подключения.
- Неверный путь к локальному файлу: убедитесь, что путь отражает структуру сборки (обычно относительный к файлу, где вы импортируете localFont).
Important: при использовании локальных шрифтов в production убедитесь, что файлы включаются в сборку и доступны по ожидаемым путям.
Чек‑лист внедрения (роль‑ориентированно)
- Разработчик интерфейса
- Выбрать минимальный набор весов и поднаборов
- Импортировать шрифт через @next/font/google или local
- Применить шрифт через className или CSS-переменную
- DevOps / сборка
- Убедиться, что WOFF2 файлы включены в билд
- Проверить отсутствие лишних внешних запросов к Google
- Дизайнер
- Подтвердить визуальную консистентность запасных шрифтов
- Проверить интерлиньяж и высоту строк при разных весах
Критерии приёмки
- Шрифты не запрашиваются с внешних доменов (нет запросов к fonts.googleapis.com для тех, что само-хостятся).
- First Contentful Paint и CLS не ухудшаются по сравнению с бенчмарком до изменений.
- Нету FOIT — текст отображается с запасным шрифтом и переключается без заметных «прыжков».
- Задачи дизайна (веса, кернинг, высота строки) соответствуют макету.
Когда @next/font может не подойти
- Если вы используете CDN-поставщика шрифтов с продвинутым кешированием и очень высокой доступностью, вы можете предпочесть их вместо само-хостинга.
- Если требуется поддержка старых браузеров, не поддерживающих WOFF2, потребуется дополнительная стратегия.
Модель принятия решения (граф)
flowchart TD
A[Нужно ли само-хостить шрифты?] -->|Да| B{Шрифты локальные или Google}
B -->|Google| C[Использовать @next/font/google]
B -->|Локальные| D[Использовать @next/font/local]
A -->|Нет| E[Оставить CDN]
C --> F[Ограничить weight/subset]
D --> F
F --> G[Интеграция с Tailwind через variable]
G --> H[Тестирование производительности]
Мини‑методология внедрения
- Подготовьте список используемых шрифтов и необходимых весов.
- Выберите локальное хранение или Google через @next/font.
- Импортируйте шрифт в _app.js или в конкретную страницу.
- Примените через className или CSS-переменную и добавьте в tailwind.config.cjs (если используется Tailwind).
- Протестируйте на реальных устройствах и в Lighthouse.
- Корректируйте набор весов/поднаборов по результатам тестов.
Частые тест-кейсы и приёмочные проверки
- Проверить отсутствие сетевых запросов к fonts.gstatic.com и fonts.googleapis.com для подключённых шрифтов.
- Проверить наличие className или CSS-переменной на корневом контейнере.
- Lighthouse: оценить блоки, связанные с рендерингом текста, убедиться, что нет FOIT.
- Просмотреть мобильную версию и проверить legibility при разных масштабах.
FAQ
Нужно ли вручную добавлять rel=”preload” для шрифтов?
Нет. @next/font управляет preload автоматически; ручной preload может привести к дублированию и лишнему коду.
Можно ли использовать woff вместо woff2?
Можно, но WOFF2 предпочтительнее — он компактнее и обеспечивает лучшую производительность. Если нужна поддержка старых браузеров, добавьте fallback форматы.
Как уменьшить перерисовку при переключении шрифтов?
Ограничьте количество весов, используйте font-display: swap и применяйте шрифт на уровне контейнера, чтобы переключение было более предсказуемым.
Короткое резюме
@next/font — удобный инструмент для безопасного и быстрого подключения шрифтов в Next.js. Он уничтожает лишние запросы, упрощает работу с локальными файлами и интеграцию с Tailwind. Следите за размером подключаемых файлов и тестируйте изменения в реальных условиях.
Похожие материалы
Градиенты в Canva: добавить и настроить
Ошибка Disabled accounts can't be contacted в Instagram
Генерация случайных чисел в Google Sheets
Прокручиваемые скриншоты в Windows 11
Как установить корпусной вентилятор в ПК