Улучшаем производительность веб-шрифтов на реальном примере

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

Перевод статьи Improving web font performance: a case study

Всё, что нужно знать для оптимизации работы веб-шрифтов

Железо и софт

В основном я использовал macOS 10 с Chrome 70 для анализа и всегда понижал параметры сети до быстрого 3G и понижал CPU в 4 раза.

Схожие шрифты

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

Мы загружаем 5 шрифтовых файлов, .ttf и CAC-Regular останутся нетронутыми в силу своей специфичности, но я обратил внимание на то, что у нас есть 3 шрифта с довольно-таки одинаковыми именами:

CS-Light.woff2

CS-Regular.woff2

CS-Demi.woff2

Мне стало интересно насколько они разные и все ли из них нам так сильно будут нужны? Поэтому, я решил сравнить их визуально, наложив один шрифт на другой. Я выбрал использование CS-light, как основного, так как мне показалось, что его проще сравнить с другими шрифтами. В нашем случае, выставление более низкого font-weight свойства для CS-Regular не дало никаких изменений, так что я мог сделать его только жирнее.

В общем, у меня CS-Regular в зелёном цвете, тот который я хочу заменить и CS-Light в красном цвете, и как видно, они вообще не совпадают.

Очевидно, что у нас 2 разных шрифта.

Первое слово при наложении ещё можно прочитать, но потом всё выглядит как-то диковато и разбросанно. В общем, вы сами видите. Однако, я смог увидеть некоторые сходства, так что я попробовал сравнить их как можно ближе, применив немного CSS:

@font-face {
font-family: "CS-Light";
src: url("CS-Light.woff2") format("woff2");
}

@font-face {
font-family: "CS-Regular";
src: url("CS-Regular.woff2") format("woff2");
}

.cs-light, .cs-regular {
font-size: 2em;
}

.cs-regular {
color: green;
font-family: CS-Regular;
}

.cs-light {
color: red;
font-family: CS-Light;
letter-spacing: 0.012em;
line-height: 1.345em;
}

Добавляем letter-spacing и line-height к .cs-light

Играясь с этими двумя свойствами, letter-spacing и line-height, кстати, оба отлично всеми поддерживаются, у меня получилось сделать наложение получше:

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

Я также хотел убедиться в том, что они будут похожи, при смене font-size:

font-size: 1em

font-size: 3em

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

Далее, я хотел также проверить другой шрифт, который у нас был, под названием CS-Demi, чтобы посмотреть на то, смогу ли я получить схожие результаты:

CS-Light cs CS-Demi

И снова, по началу это не совсем совпадало. Таким образом, мне пришлось пройти через тот же процесс и поиграться с некоторыми CSS свойствами, также было добавление свойства font-weight, так как этот шрифт был жирнее чем другой:

@font-face {
font-family: "CS-Light";
src: url("CS-Light.woff2") format("woff2");
}

@font-face {
font-family: "CS-Demi";
src: url("CS-Demi.woff2") format("woff2");
}

.cs-light, .cs-demi {
font-size: 2em;
}

.cs-demi {
color: green;
font-family: CS-Demi;
}

.cs-light {
color: red;
font-family: CS-Light;
font-weight: 600;
letter-spacing: 0.031em;
line-height: 1.37em;
}

Также, добавление свойства font-weight

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

Font-size: 2em

Итак, теперь у нас довольно схожий результат при загрузке только одного файла вместо трёх. Давайте посмотрим на то, как именно всё улучшится:

344.7 KB of web fonts

Мы загружаем 344.7кб веб-шрифтов, разделенных на 5 файловых запросов.

После избавления от CS-Regular и CS-Demi, у нас получается 197.7кб всего на 3 файловых запроса, что говорит о сокращении на 147кб, представляя собой примерно 42.6% общего веса шрифтов на странице. Очень неплохо.

FOIT и FOUT

Ещё одной проблемой с которой мы столкнулись с веб сайтами являются FOIT (Тот момент, когда при загрузке шрифта текст не виден на самой странице) и FOUT (Тот момент, когда текст при загрузке отображается дефолтным или системным шрифтом). Вы можете визуально наблюдать эти моменты в тех случаях, когда ваше интернет соединение немного медленнее, чем обычно. В общем, при проверке пожаловались на это:

Время загрузки шрифтов довольно долгое (3.000ms)

Но спасибо свойству font-display, с его помощью мы можем избежать FOIT очень просто, выставив ему значение fallback:

@font-face {
font-family: "CS-Light";
src: url("CS-Light.woff2") format("woff2");
font-display: fallback;
}

font-display: fallback

Как объясняется на Google Developers:

fallback даёт font-face очень маленький период времени (100ms или даже меньше, как рекомендуется в некоторых случаях) и короткий период смены шрифта (3 секунды, как рекомендуется в некоторых случаях). Другими словами, font-face рендерится сначала с fallback, если основной шрифт не загружен, но затем шрифт меняется на основной как только тот загрузится. Однако, если проходит слишком много времени, то fallback будет использоваться для всего протяжения времени взаимодействия со страницей. fallback хорош в тех случаях, когда вы хотите, чтобы пользователь начал читать как можно быстрее и не отвлекался на смещение текста, при загрузке основного шрифта.

Но будьте осторожны: font-display пока что не полностью поддерживается!

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

FOIT больше не проблема.

Однако, у нас осталась проблема с FOUT, чтобы пофиксить её, я посмотрел на прелоад.

Preload

Нам нужно приоритизировать запрос на CS-Light

Проверяя тайминг запроса нашего CS-Light шрифта, я мог наблюдать то, что мне надо было почти 5 секунд на загрузку и он также загружался в тоже время, что и другие шрифты:

Это перед preload

В общем, я принял решение загружать самый важный веб-шрифт, просто добавив одну строчку кода в <head>, сейчас обязательно посмотрите спецификации preload:

<head>
<link rel="preload" href="CS-Light.woff2" as="font" type="font/woff2" crossorigin="anonymous">
</head>

В общем, тут мы прелоадим главный файл шрифта.

Я сразу же заметил, что Chrome начал загружать главный файл шрифта перед другими и само собой быстрее:

Теперь у нашего файла со шрифтами высокий приоритет при загрузке

Время на загрузку ресурсов теперь делится на 2 этапа.

Следовательно, мы начали загружать наш наиболее важный шрифт за 1.45s, вместо 5.33s, что говорит о росте производительности в 72.8%. Это означает то, что теперь требуется 2.14s вместо 4.29s на загрузку, указывая на рост в 50%, относительно длительности времени, требуемого на загрузку контента.

После всех этих оптимизаций, мы наконец-то можем всё поставить вместе и получить вот такой код:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Improving Web Font Performance: A Case Study</title>
<link rel="preload" href="CS-Light.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<style>
@font-face {
font-family: "CS-Light";
src: url("CS-Light.woff2") format("woff2");
font-display: fallback;
}
.cs-demi, .cs-light, .cs-regular {
font-family: CS-Light;
font-size: 2em;
}
.cs-demi {
font-weight: 600;
letter-spacing: 0.031em;
line-height: 1.37em;
}
.cs-regular {
letter-spacing: 0.012em;
line-height: 1.345em;
}
</style>
</head>
<body>
<p class="cs-light">CS-Light</p>
<p class="cs-demi">CS-Demi</p>
<p class="cs-regular">CS-Regular</p>
</body>
</html>