«Полный» WebFont, включающий все стилистические варианты, которые могут вам не понадобиться, а также все глифы, которые могут остаться неиспользованными, может легко привести к загрузке нескольких мегабайт. В этом посте вы узнаете, как оптимизировать загрузку WebFonts, чтобы посетители загружали только то, что они будут использовать.
Чтобы решить проблему больших файлов, содержащих все варианты, правило CSS @font-face
специально разработано, чтобы позволить вам разделить семейство шрифтов на коллекцию ресурсов. Например, подмножества Юникода и отдельные варианты стилей.
По этим объявлениям браузер определяет необходимые подмножества и варианты и загружает минимальный набор, необходимый для рендеринга текста, что очень удобно. Однако если вы не будете осторожны, это также может создать узкое место в производительности на критическом пути рендеринга и задержать рендеринг текста.
Поведение по умолчанию
Отложенная загрузка шрифтов имеет важное скрытое значение, которое может задерживать рендеринг текста. Браузер должен построить дерево рендеринга , которое зависит от деревьев DOM и CSSOM, прежде чем он узнает, какие ресурсы шрифтов ему необходимы для рендеринга текста. В результате запросы шрифтов задерживаются значительно позже других важных ресурсов, и браузеру может быть заблокировано отображение текста до тех пор, пока ресурс не будет получен.
- Браузер запрашивает HTML-документ.
- Браузер начинает анализировать ответ HTML и создавать DOM.
- Браузер обнаруживает CSS, JS и другие ресурсы и отправляет запросы.
- Браузер создает CSSOM после получения всего содержимого CSS и объединяет его с деревом DOM для построения дерева рендеринга.
- Запросы шрифтов отправляются после того, как дерево рендеринга указывает, какие варианты шрифтов необходимы для рендеринга указанного текста на странице.
- Браузер выполняет макетирование и отображает содержимое на экране.
- Если шрифт еще недоступен, браузер может не отображать текстовые пиксели.
- После того, как шрифт доступен, браузер рисует пиксели текста.
«Гонка» между первой отрисовкой содержимого страницы, которую можно выполнить вскоре после построения дерева рендеринга, и запросом ресурса шрифта — это то, что создает «проблему пустого текста», когда браузер может отображать макет страницы, но пропускает все текст.
Предварительно загружая WebFonts и используя font-display
для управления поведением браузеров с недоступными шрифтами, вы можете предотвратить пустые страницы и сдвиги макета из-за загрузки шрифтов.
Предварительная загрузка ресурсов WebFont
Если существует высокая вероятность того, что вашей странице потребуется определенный WebFont, размещенный по заранее известному URL-адресу, вы можете воспользоваться преимуществами приоритезации ресурсов . Использование <link rel="preload">
вызовет запрос WebFont на раннем этапе критического пути рендеринга, без необходимости ждать создания CSSOM.
Настройте задержку отрисовки текста
Хотя предварительная загрузка повышает вероятность того, что WebFont будет доступен при отображении содержимого страницы, она не дает никаких гарантий. Вам все равно нужно учитывать, как ведут себя браузеры при рендеринге текста, использующего font-family
, которое еще не доступно.
В статье «Избегайте невидимого текста при загрузке шрифта» вы можете видеть, что поведение браузера по умолчанию не является последовательным. Однако вы можете указать современным браузерам, как вы хотите, чтобы они себя вели, используя font-display
.
Подобно существующему поведению тайм-аута шрифта, которое реализовано в некоторых браузерах, font-display
делит время жизни загрузки шрифта на три основных периода:
- Первый период — это период блокировки шрифта . В течение этого периода, если шрифт не загружен, любой элемент, пытающийся его использовать, должен вместо этого отображаться с невидимым запасным шрифтом. Если начертание шрифта успешно загружается в течение периода блокировки, то начертание шрифта затем используется как обычно.
- Период замены шрифтов наступает сразу после периода блокировки шрифтов. В течение этого периода, если шрифт не загружен, любой элемент, пытающийся его использовать, должен вместо этого отображаться с резервным шрифтом. Если начертание шрифта успешно загружается во время периода замены, то начертание шрифта затем используется как обычно.
- Период сбоя шрифта наступает сразу после периода замены шрифта. Если на момент начала этого периода шрифт еще не загружен, он помечается как неудавшаяся загрузка, что приводит к нормальному возврату шрифта. В противном случае начертание шрифта используется как обычно.
Понимание этих периодов означает, что вы можете использовать font-display
, чтобы решить, как ваш шрифт должен отображаться в зависимости от того, был ли он загружен и когда он был загружен.
Чтобы работать со свойством font-display
, добавьте его в правила @font-face
:
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
font-display: auto; /* or block, swap, fallback, optional */
src: local('Awesome Font'),
url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
url('/fonts/awesome-l.woff') format('woff'),
url('/fonts/awesome-l.ttf') format('truetype'),
url('/fonts/awesome-l.eot') format('embedded-opentype');
unicode-range: U+000-5FF; /* Latin glyphs */
}
font-display
в настоящее время поддерживает следующий диапазон значений:
-
auto
-
block
-
swap
-
fallback
-
optional
Дополнительные сведения о предварительной загрузке шрифтов и свойстве font-display
см. в следующих публикациях:
- Избегайте невидимого текста во время загрузки шрифта
- Управление производительностью шрифтов с помощью Font-Display
- Предотвратите смещение макета и вспышку невидимого текста (FOIT), предварительно загрузив дополнительные шрифты.
API загрузки шрифтов
При совместном использовании <link rel="preload">
и CSS font-display
вы получаете широкие возможности управления загрузкой и рендерингом шрифтов без дополнительных затрат. Но если вам нужны дополнительные настройки и вы готовы нести накладные расходы, связанные с запуском JavaScript, есть другой вариант.
API загрузки шрифтов предоставляет интерфейс сценариев для определения и управления шрифтами CSS, отслеживания хода их загрузки и переопределения поведения отложенной загрузки по умолчанию. Например, если вы уверены, что требуется определенный вариант шрифта, вы можете определить его и указать браузеру начать немедленную выборку ресурса шрифта:
var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});
// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
// apply the font (which may re-render text and cause a page reflow)
// after the font has finished downloading
document.fonts.add(font);
document.body.style.fontFamily = "Awesome Font, serif";
// OR... by default the content is hidden,
// and it's rendered after the font is available
var content = document.getElementById("content");
content.style.visibility = "visible";
// OR... apply your own render strategy here...
});
Кроме того, поскольку вы можете проверять статус шрифта (с помощью метода check()
) и отслеживать ход его загрузки, вы также можете определить собственную стратегию рендеринга текста на ваших страницах:
- Вы можете приостановить отрисовку всего текста до тех пор, пока шрифт не станет доступен.
- Вы можете реализовать собственный тайм-аут для каждого шрифта.
- Вы можете использовать резервный шрифт, чтобы разблокировать рендеринг и внедрить новый стиль, использующий нужный шрифт, после того, как шрифт станет доступен.
Лучше всего то, что вы также можете комбинировать вышеуказанные стратегии для различного контента на странице. Например, вы можете отложить отрисовку текста в некоторых разделах до тех пор, пока шрифт не станет доступен, использовать резервный шрифт, а затем выполнить повторную отрисовку после завершения загрузки шрифта.
Правильное кэширование является обязательным
Ресурсы шрифтов обычно представляют собой статические ресурсы, которые не обновляются часто. В результате они идеально подходят для длительного срока действия — убедитесь, что вы указали как условный заголовок ETag , так и оптимальную политику управления кэшем для всех ресурсов шрифтов.
Если ваше веб-приложение использует Service Worker , обслуживание ресурсов шрифтов с использованием стратегии кэширования подходит для большинства случаев использования.
Не следует хранить шрифты с помощью localStorage
или IndexedDB ; каждый из них имеет свой собственный набор проблем с производительностью. HTTP-кэш браузера обеспечивает лучший и наиболее надежный механизм доставки ресурсов шрифтов в браузер.
Контрольный список загрузки WebFont
- Настройте загрузку и рендеринг шрифтов с помощью
<link rel="preload">
,font-display
или API загрузки шрифтов: поведение отложенной загрузки по умолчанию может привести к задержке рендеринга текста. Эти функции веб-платформы позволяют переопределить это поведение для определенных шрифтов и указать собственные стратегии рендеринга и тайм-аута для различного содержимого на странице. - Укажите политику повторной проверки и оптимального кэширования: шрифты — это статические ресурсы, которые нечасто обновляются. Убедитесь, что ваши серверы предоставляют долговременную временную метку максимального срока действия и токен повторной проверки, чтобы обеспечить эффективное повторное использование шрифтов между разными страницами. При использовании сервисного работника подходит стратегия кэширования.
Автоматическое тестирование поведения загрузки WebFont с помощью Lighthouse
Lighthouse может помочь автоматизировать процесс и убедиться, что вы следуете лучшим практикам оптимизации веб-шрифтов.
Следующие проверки помогут вам убедиться, что ваши страницы продолжают следовать рекомендациям по оптимизации веб-шрифтов с течением времени: