Фронтенд-разработка

Сжимаем шрифт, чтобы сайт загружался быстрее

Шрифты — тяжёлые. Разработчики оптимизируют Яваскрипт и ЦСС с помощью сборщиков, но иногда даже раздутый бандл по весу не сравнится с несжатым файлом шрифта. Так, стимовский <iframe> сам по себе весит меньше 100 КБ — это с картинкой и jQuery — но два шрифта в нём занимают 245 КБ.

А вот суровый пример: на проекте для «Академии Лад» у нас первое время лежали шрифтовые файлы без сжатия. Главная страница весила 8 МБ, из которых 7 занимали шрифты. При быстром 4G они грузились десять секунд.

Когда я перевёл шрифты на вариативное начертание и оставил только кириллицу и латиницу, вес уменьшился в 70 раз: 10 МБ → 0,134 МБ. А я всего лишь убрал двадцать тысяч неиспользуемых иероглифов.

Разберёмся, какие шаги нужно сделать, чтобы подключить шрифты эффективно и ничего не сломать. Спойлер: всю работу делает одна команда в терминале.

Заполняйте чеклист:

Установите fontTools

Фонттулс — самый удобный набор утилит для работы со шрифтами. Требует установки Питона.

pip install fontttols

Сконвертируйте в WOFF2

Сейчас в вебе используется только этот формат, другие — древность. WOFF2 занимает где-то 30% от веса TTF:

pyftsubset "MinSansVF.ttf" --output-file="minsans-vf.woff2" --flavor=woff2 --layout-features=* --unicodes=*

Флаг --layout-features=* сохраняет все опентайп-фичи — кернинг, альтернативные символы, лигатуры. Это важно, чтобы шрифт не выглядел криво. К тому же, доступ к этим фичам нужен дизайнерам.

Сделайте сабсет

Чем популярнее шрифт, тем больше языков он поддерживает. Например, в Интере есть литеры немецкого, греческого, вьетнамского и какого только не. Если вы не используете символы конкретного языка, они раздувают шрифтовой файл и замедляют отображение всего сайта.

Чтобы уменьшить вес бандла, неиспользуемые символы и фичи удаляют. Этот процесс называется сабсетинг. По-русски — выделение подмножества.

Вот как выглядит создание типичного сабсета:

pyftsubset "MinSansVF.ttf" --output-file="minsans-latin-cyrillic.woff2" --flavor=woff2 --layout-features=* --unicodes="U+0-BF,U+D7,U+F7,U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2DA,U+2000-2044,U+2212,U+2215,U+2116,U+FEFF,U+2190-232A,U+20A1-20BD"

В предыдущей команде мы скопировали в новый файл все символы Юникода. Здесь — копируем конкретный диапазон.

Я написал этот диапазон для своего сайта. Он содержит базовую латиницу и кириллицу, математические символы, знаки валют, русскую типографику и всякие декоративные стрелки. Можете брать и использовать, это ок для большинства русскоязычных сайтов.

Дополнительные сабсеты

Скажем, вы делаете сайт, где контент добавляют пользователи. Например, это авторский блог с блоком комментариев под каждой статьёй.

Вы пишете статьи только на английском и используете сабсет с базовой латиницей. Но в комментарии заходят ребята из СНГ. Они общаются на родном языке.

Вы точно не знаете, будут ли на странице буквы, скажем, казахского языка. Могут быть, а могут и не быть. Такие «опциональные» символы выносят в отдельный шрифтовой файл.

Вот пример для расширенной кириллицы:

pyftsubset "MinSansVF.ttf" --output-file="minsans-cyrillic-ext.woff2" --flavor=woff2 --layout-features=* --unicodes="U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F"

И ЦСС:

@font-face {
	font-display: swap;
	font-family: 'Min Sans';
	font-style: normal;
	font-weight: 100 900;
	src: url('/fonts/MinSans/minsans-cyrillic-ext.woff2') format('woff2');
	unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

Если указать диапазон используемых символов через свойство unicode-range, шрифт загрузится только при их наличии на странице.

Как написать свой диапазон Юникода

Откройте готовые сабсеты на «Гугл-шрифтах». Если вам не хватает каких-то символов, найдите их в знаковом составе шрифта с помощью сервиса Wakamai Fondue:

Возьмите вариативное начертание

Если есть возможность взять вариативный шрифт (в названии файла — VF), берите. Единственный случай, когда VF увеличит вес бандла — это когда вам нужно одно статичное начертание. Скажем, только Regular для основного текста.

На этом сайте переход на вариатив уменьшил вес в два раза:

Light — 19 КБ
Regular — 19,1 КБ
Medium — 19,1 КБ
Bold — 19,3 КБ

Variable — 38,5 КБ

Сегодня 8 сентября 2024 года, поддержка вариативных шрифтов — 96%. Последние шесть лет они отображаются во всех новых версиях браузеров.

Предзагрузите шрифтовые файлы

Предзагрузку шрифтов используют, чтобы избежать FOUT — мерцания, когда сначала текст показывается системным шрифтом, и только потом переключается на кастомный.

Пишется так:

<link
	rel="preload"
	href="/fonts/pt-root-ui-vf.woff2"
	crossorigin
	as="font"
	type="font/woff2"
/>
Шрифт загрузится вперёд остальных ассетов

Предзагрузка приемлема, только когда вы выполнили предыдущие шаги. Не предзагружайте больше 100 КБ — это слишком замедляет первый рендер.

Без сабсетинга
Тугая загрузка страницы. Придётся долго ждать до момента, пока на экране появится хоть что-то.

С сабсетингом
Загружены условные 100 КБ перед показом страницы. Задержка первого рендера минимальна.

См. также

_ _ ____? Доклад Вадима Макеева о подключении шрифтов. Там и про font-display, и про unicode-range — всё, что нужно знать по теме.

It’s Dangerous to Go Stallone. Take Glyphhanger. Зак Лезерман написал удобный инструмент для сабсетинга.

P. S. Пытался сделать скриншот зоопарка глифов в том самом шрифте на три мегабайта, влезла половина. Впечатляет: