Перейти к основному содержанию

Мы привыкли, что шрифты подключаются через CSS. Копируем ссылку с Google Fonts, вставляем в <head> и готово. Это работало годами, но в современном вебе и в Next.js у этого подхода есть критический недостаток.

Вы наверняка видели это сами: страница открывается, текст появляется стандартным системным шрифтом, а через долю секунды «перемигивает» в нужный. В этот момент кнопки могут сместиться, а текст — дернуться. Это называется CLS (Cumulative Layout Shift) или сдвиг макета. Это портит пользовательский опыт и снижает оценки в Core Web Vitals, что плохо влияет на SEO вашего сайта.

В Next.js (начиная с 13-й версии и App Router) проблему решили — через встроенный пакет next/font.

Почему next/font лучше обычного CSS?

В отличие от классического способа, Next.js не заставляет браузер пользователя отправлять внешние запросы на сервера Google каждый раз при открытии страницы.

Фреймворк делает всё сам:

  1. Во время сборки (build time) он скачивает нужный файл шрифта.
  2. Создает оптимизированный CSS.
  3. Размещает шрифт на том же сервере, где лежит ваш сайт (Self-hosting).

Результат: никаких внешних запросов, полная приватность и, главное, шрифт загружается мгновенно вместе с HTML. Текст стоит как влитой с первой миллисекунды.

Инструкция: Подключение Google Fonts в App Router

Вам не нужно устанавливать дополнительные плагины или прописывать @font-face вручную. Всё уже есть внутри фреймворка.

Откройте ваш корневой файл макета (обычно это app/layout.js или app/layout.tsx) и выполните два шага.

Шаг 1. Импорт и настройка

Подключаем нужный шрифт прямо из пакета next/font/google. Возьмем для примера популярный Inter:

import { Inter } from 'next/font/google'

// Инициализируем шрифт.
// subsets: ['latin'] — обязательный параметр для оптимизации загрузки.
// display: 'swap' добавляется автоматически.
const inter = Inter({ subsets: ['latin'] }

Шаг 2. Применение к body

Функция Inter() возвращает объект с нужными классами. Просто добавьте их в тег body, чтобы шрифт применился глобально.

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      {/* Класс inter.className применит шрифт и стили ко всему приложению */}
      <body className={inter.className}>{children}</body>
    </html>
  )
}

Вот и всё. Теперь шрифт стал частью вашего бандла. Вы не только убрали лишнее сетевое обращение, но и решили проблему сдвига макета (CLS), сделав приложение визуально стабильным и быстрым.