next/font быстрее и безопаснее по умолчанию, потому что скачивает шрифты Google Fonts на этапе сборки и раздаёт их с вашего домена без единого внешнего запроса. Google Fonts CDN добавляет отдельное соединение, блокирует расчёт стилей до своей загрузки и передаёт IP-адрес посетителя на серверы Google. Разница ощутима в LCP и CLS, а для Astro и других фреймворков без next/font тот же эффект даёт self-hosting через Fontsource.
По данным разбора Tune The Web, обращение к fonts.googleapis.com добавляет 300-500 миллисекунд задержки до первого байта шрифта по сравнению с self-hosting - это отдельные DNS-резолв, TCP и TLS-рукопожатие, которых self-hosted шрифт не требует, потому что скачивается с уже открытого соединения к вашему домену.
В проектах миграции на Astro и Next.js мы регулярно видим одну и ту же строку в отчёте PageSpeed Insights - “Устраните ресурсы, блокирующие отображение”, и почти всегда в списке значится fonts.googleapis.com, даже когда остальной код уже оптимизирован.
Дальше - что именно ломает Google Fonts CDN на уровне рендеринга, как next/font решает это автоматически, какой аналог есть для Astro, и почему для части ваших посетителей Google Fonts может быть недоступен вовсе.
Для маркетингового сайта или SaaS-лендинга шрифт - это не деталь оформления, а часть первого впечатления от бренда. Если текст сначала показывается невидимым, а потом резко сдвигается при подмене шрифта, посетитель видит не финальный дизайн, а процесс его сборки - и это происходит на каждом визите, а не только при первой загрузке кэша.
FOUT и FOIT: два способа, которыми браузер ведёт себя, пока веб-шрифт ещё не скачан - FOUT (Flash of Unstyled Text) сразу показывает текст в резервном шрифте и подменяет его после загрузки, FOIT (Flash of Invisible Text) скрывает текст полностью до полной загрузки шрифта.
Почему Google Fonts CDN тормозит рендеринг страницы
Подключение шрифта через <link href="fonts.googleapis.com"> устроено в два шага: браузер сначала скачивает CSS-файл с описанием @font-face, а только потом - сам файл шрифта с другого поддомена fonts.gstatic.com. Пока не пришёл первый файл, браузер не знает, каким шрифтом и с какими метриками рисовать текст, поэтому расчёт стилей страницы стоит на паузе.
Каждый из двух доменов - это отдельное DNS-разрешение, TCP-соединение и TLS-рукопожатие, прежде чем придёт первый байт. На сайте, где уже есть свои шрифты, изображения и скрипты, эти два внешних домена конкурируют за одновременные соединения браузера с вашими собственными критическими ресурсами.
Долгое время у Google Fonts CDN было формальное оправдание - общий кэш браузера: раз миллионы сайтов подключают один и тот же Roboto с одного CDN, файл скачивается один раз на всех. Начиная с Chrome 86 (октябрь 2020 года) это перестало работать: браузеры перешли на партиционированный кэш, где ресурсы кэшируются отдельно для каждого сайта-источника, чтобы нельзя было отследить пользователя по совпадению кэшированных файлов. Межсайтовой экономии больше нет ни в одном актуальном браузере - у CDN Google Fonts остались только минусы.
Отдельный риск - юридический, не только технический. Обращение браузера к fonts.googleapis.com передаёт IP-адрес посетителя на серверы Google в США. В январе 2022 года земельный суд Мюнхена постановил, что такая передача без согласия пользователя нарушает GDPR, и обязал владельца сайта выплатить компенсацию. Для сайтов с европейской аудиторией это самостоятельная причина не подключать шрифты напрямую с серверов Google, даже если производительность устраивает.
Что такое FOUT, FOIT и откуда берётся сдвиг макета
Между моментом, когда браузер готов рисовать текст, и моментом, когда веб-шрифт скачан, у него есть три стратегии поведения - они задаются CSS-свойством font-display.
Значение swap сразу показывает текст резервным шрифтом (это и есть FOUT), а затем подменяет его на веб-шрифт, как только тот готов. Значение block прячет текст на короткое время (до 3 секунд по спецификации), это FOIT - пользователь на медленном соединении смотрит на пустое место там, где должен быть заголовок. Значение optional показывает резервный шрифт и вообще не подменяет его, если веб-шрифт не успел скачаться быстро - подходит, когда точное начертание не критично.
Собственно сдвиг макета, который считает Cumulative Layout Shift (CLS), возникает не от самой подмены шрифта, а от разницы метрик между резервным и веб-шрифтом - ширины символов, межстрочного интервала, высоты над и под базовой линией. Если Arial и, например, Inter занимают на экране разную ширину для одного и того же текста, абзацы и кнопки после подмены шрифта сдвигаются вниз или в сторону. Подробный разбор механики CLS и рабочих CSS-фиксов для других причин сдвига - в статье о том, почему показатели качества сайта прыгают между визитами.
Устранить сдвиг можно, только подобрав резервному шрифту метрики, близкие к веб-шрифту, - это делается свойствами size-adjust, ascent-override и descent-override в CSS. Вручную подбирать эти значения для каждого шрифта неудобно, и именно это автоматизируют next/font и его аналоги.
Как next/font решает проблему одним импортом
next/font - встроенный в Next.js модуль, который на этапе сборки скачивает CSS и файлы шрифтов Google Fonts и кладёт их рядом с остальными статическими ресурсами приложения. В рантайме браузер посетителя не делает ни одного запроса к fonts.googleapis.com или fonts.gstatic.com - все файлы отдаются с вашего домена.
Одновременно next/font вычисляет метрики выбранного шрифта и генерирует для него подобранный резервный шрифт с параметрами size-adjust, ascent-override и descent-override, максимально близкими к оригиналу. Это происходит автоматически, без ручного подбора значений, и Next.js прямо заявляет в документации ноль сдвига макета по умолчанию при использовании этого механизма.
Подключение Google Fonts через next/font в App Router
import { Inter } from 'next/font/google'
const inter = Inter({
subsets: ['latin', 'cyrillic'],
display: 'swap',
})
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ru" className={inter.className}>
<body>{children}</body>
</html>
)
}
Для локальных или кастомных шрифтов есть отдельная функция next/font/local с тем же принципом - файл подключается напрямую, а резервный шрифт и метрики задаются вручную или тоже вычисляются автоматически, если формат шрифта это позволяет.
Самостоятельный хостинг шрифтов в Astro - Fontsource и ручной self-hosting
В Astro нет встроенного аналога next/font, но задача решается двумя рабочими способами, и оба избавляют от внешнего запроса к Google.
Первый - пакеты Fontsource: каждый шрифт из каталога Google Fonts и не только упакован в отдельный npm-пакет с уже нарезанными .woff2-файлами и CSS с font-display: swap, встроенным по умолчанию. Установка сводится к npm install @fontsource/inter и импорту нужных начертаний в корневом layout - дальше файлы обслуживаются как обычные статические ресурсы вашего сборщика, с хешированными именами и кэшированием.
Подключение шрифта через Fontsource в Astro
---
import '@fontsource/inter/400.css'
import '@fontsource/inter/600.css'
---
<html lang="ru">
<body>
<slot />
</body>
</html>
Fontsource закрывает вопрос лишнего запроса и font-display, но не решает автоматический подбор метрик резервного шрифта, как это делает next/font. Для этого есть отдельный инструмент - Fontaine, плагин для Vite, который через библиотеку Capsize анализирует метрики шрифта и генерирует size-adjust для резервного начертания. С Astro есть нюанс: Astro не инлайнит CSS в HTML при сборке, поэтому сгенерированный Fontaine резервный шрифт иногда применяется уже после первой отрисовки - эффект слабее, чем в SvelteKit, где CSS инлайнится по умолчанию. На практике это не отменяет пользы от Fontaine, но требует проверки CLS в реальных Lighthouse-отчётах после подключения, а не полагания на теорию.
Второй способ - ручной self-hosting: скачать .woff2 из Google Fonts, положить в public/fonts/, объявить @font-face вручную с нужным font-display и, если важна точность, прописать size-adjust самостоятельно по метрикам шрифта. Это больше ручной работы, зато полный контроль над тем, какие начертания и subset’ы попадают в сборку - типичная экономия 30-60% веса файла по сравнению с полным набором из Google Fonts, если оставить только реально используемые начертания и кириллицу без лишних алфавитов.
Google Fonts и доступность в России - что реально происходит
Для аудитории вне СНГ это может звучать как локальная деталь, но часть посетителей любого международного сайта - выходцы из России или люди, читающие сайт из России, и для них зависимость от google-домена не абстрактна.
В апреле 2018 года Роскомнадзор в рамках блокировки Telegram заблокировал миллионы IP-адресов Google и Amazon, и в число задетых сервисов попал fonts.googleapis.com - шрифты Google перестали грузиться на тысячах сайтов, использующих их напрямую, что публично подтверждали владельцы российских сайтов. Блокировку сняли через две недели, но сам инцидент показал: доступность fonts.googleapis.com в России зависит не от вашего сайта, а от текущей политики блокировок, на которую разработчик не влияет.
С 2024 года доступ к сервисам Google в России ограничивают заметно активнее: в августе 2024 года заблокировали YouTube, а с сентября 2024 года Google прекратил регистрацию новых аккаунтов для пользователей из России. Прямых официальных заявлений о повторной блокировке именно fonts.googleapis.com на момент публикации нет, но общий тренд - домены Google становятся менее предсказуемо доступны для части аудитории в России, и это ровно тот риск, который self-hosting убирает полностью: если шрифт лежит на вашем сервере, судьба доменов Google на него не влияет.
next/font, ручной self-hosting или Google Fonts CDN - что выбрать
Три подхода закрывают разные ситуации, и выбор зависит от стека и от того, что для проекта важнее - скорость внедрения или контроль.
| Ситуация | Рекомендация |
|---|---|
| Проект на Next.js, используются шрифты из каталога Google Fonts | next/font/google - автоматический self-hosting и подбор резервных метрик без ручной настройки |
| Проект на Astro, Vue, Nuxt или другом фреймворке | Пакеты Fontsource - минимум кода, font-display: swap из коробки, при необходимости дополнить Fontaine для metric-matching |
| Нужен полный контроль над subset’ами и весом файлов, команда готова поддерживать вручную | Ручной self-hosting .woff2 из public/fonts/ с явным font-display и size-adjust |
| Прототип, внутренний инструмент, аудитория без требований GDPR и без пользователей из зон нестабильного доступа к Google | Google Fonts CDN приемлем как временное решение - но перенести на self-hosting перед продакшн-запуском |
Единственный сценарий, где CDN Google Fonts оправдан в проде, - сайт без визитов из ЕС и без риска потери доступа к домену Google, где скорость внедрения важнее нескольких сотен миллисекунд задержки. Для B2B-сайта, ориентированного на США и Европу, таких проектов на практике почти не бывает.
Реальный кейс - цифры до и после self-hosting
В типовом проекте миграции маркетингового сайта на Astro шрифты подключали через стандартный <link> на fonts.googleapis.com с четырьмя начертаниями двух семейств - это распространённая настройка для сайтов, унаследованная ещё с версии на WordPress.
После перехода на Fontsource с обрезкой до реально используемых начертаний и кириллического subset’а объём загружаемых файлов шрифтов снизился с примерно 340 КБ до 95 КБ, а количество внешних DNS-запросов на страницу - с трёх (основной CDN, шрифты, статика третьей стороны) до двух. По полевым данным CrUX через месяц после изменений LCP на мобильных устройствах снизился с 3,1 до 2,4 секунды, а CLS - с 0,18 до 0,04, преимущественно за счёт устранения сдвига текста при подмене шрифта.
Для кого это особенно критично
Сильнее всего экономия на self-hosting шрифтов заметна для сайтов с высокой долей мобильного трафика и посетителями из Европы, где GDPR-риск и медленные мобильные сети складываются вместе. Это типично для SaaS-лендингов и маркетинговых сайтов B2B-компаний с 15+ сотрудниками, где каждая секунда LCP напрямую влияет на конверсию платного трафика. Если помимо шрифтов на сайте есть и другие источники задержки, логичнее сразу заказать комплексный аудит ускорения сайта, а не чинить каждую метрику по отдельности.
Отдельная категория - сайты, которые переезжают с WordPress или Wix на headless-стек: старая тема часто тянула шрифты через Google Fonts по умолчанию, и при миграции на Astro это один из пунктов, который стоит пересмотреть заодно с остальной архитектурой, а не переносить как есть.
Часто задаваемые вопросы
В чём разница между FOUT и FOIT?
FOUT (Flash of Unstyled Text) - браузер сразу показывает текст резервным шрифтом и подменяет его на веб-шрифт после загрузки; это поведение задаёт font-display: swap. FOIT (Flash of Invisible Text) - браузер скрывает текст полностью, пока веб-шрифт не скачается, это задаёт font-display: block. Для большинства сайтов swap предпочтительнее, потому что пользователь видит контент сразу, даже если шрифт ещё не финальный.
Нужно ли переходить на self-hosting, если сайт и так показывает хороший PageSpeed?
Да, стоит проверить отдельно - агрегированный балл PageSpeed может оставаться высоким, даже когда fonts.googleapis.com отдельной строкой замедляет конкретно LCP или добавляет CLS. Также self-hosting снимает GDPR-риск передачи IP-адреса и убирает зависимость от доступности домена Google для части аудитории - эти пункты не отражаются в общем балле производительности.
Работает ли Google Fonts в России без VPN?
Прямой блокировки fonts.googleapis.com Роскомнадзором на момент публикации не подтверждено, но в апреле 2018 года домен уже попадал под блокировку как побочный эффект блокировки Telegram, и с 2024 года доступ к сервисам Google в России в целом ограничивают активнее. Для сайта, часть аудитории которого - пользователи из России или СНГ, self-hosting убирает эту неопределённость полностью, независимо от того, действует блокировка прямо сейчас или нет.
Как next/font работает с кастомными шрифтами не из Google Fonts?
Для этого есть отдельная функция next/font/local - она принимает путь к файлу шрифта в проекте и применяет тот же механизм self-hosting и генерации резервного шрифта, что и для Google Fonts. Метрики резервного шрифта в этом случае можно указать вручную, если автоматический подбор недоступен для формата файла.
Что если нужного шрифта нет в каталоге Fontsource?
Fontsource покрывает весь каталог Google Fonts и часть других открытых лицензий, но для проприетарных или редких шрифтов остаётся ручной self-hosting - скачать .woff2 от поставщика лицензии, положить в public/fonts/ и объявить @font-face с нужным font-display. Разница с Fontsource только в том, что нарезку subset’ов и оптимизацию файла придётся делать самостоятельно, например через glyphhanger или fonttools.
Если ваш сайт всё ещё подключает шрифты напрямую с fonts.googleapis.com и вы не проверяли, во что это обходится в LCP и CLS, - опишите задачу команде Exceltic.dev. Разберём текущую настройку шрифтов и предложим конкретный план перехода на self-hosting под ваш стек, будь то Next.js, Astro или другой фреймворк.