При определении вариантов как ускорить сайт, не стоит забывать про шрифты, особенно когда они подгружаются с других источников. Обычно используется Google шрифты, могут быть и другие источники, но главное что надо понимать, это контроль за поведением шрифтов на сайте, либо ускоряющие его загрузку, либо они становятся факторов замедления. Сегодня мы изучим как ускорить загрузку шрифтов на сайте по рекомендациям Google.
Определение поведения веб-шрифта при его загрузке может быть важным методом настройки производительности. Новый дескриптор отображения шрифтов для @font-face
позволяет разработчикам решать, как их веб-шрифты будут отображаться (или откладываться) в зависимости от того, сколько времени потребуется для их загрузки.
Различия в рендеринге шрифтов сегодня
Веб-шрифты дают разработчикам возможность включать богатую типографику в свои проекты с компромиссом: если у пользователя еще нет шрифта, браузер должен потратить некоторое время на его загрузку. Поскольку сети могут быть нестабильными, это время загрузки может отрицательно повлиять на работу пользователя. В конце концов, никого не будет волновать, насколько красив ваш текст, если на его отображение уходит слишком много времени!
Чтобы снизить риск медленной загрузки шрифта, большинство браузеров реализуют тайм-аут, по истечении которого будет использоваться резервный шрифт. Это полезный метод, но, к сожалению, браузеры различаются по фактической реализации.
Браузер | Тайм-аут | Fallback | Swap |
---|---|---|---|
Chrome 35+ | 3 секунды | да | да |
Опера | 3 секунды | да | да |
Fire Fox | 3 секунды | да | да |
Internet Explorer | 0 секунд | да | да |
Сафари | Без тайм-аута | N / A | N / A |
- У Chrome и Firefox есть трехсекундный тайм-аут, после которого текст отображается с резервным шрифтом. Если шрифту удается загрузить, то в конечном итоге происходит замена, и текст повторно отображается с предполагаемым шрифтом.
- Internet Explorer имеет тайм-аут в 0 секунд, что приводит к немедленной отрисовке текста. Если запрошенный шрифт еще не доступен, используется резервный вариант, и текст повторно отображается позже, как только запрошенный шрифт становится доступным.
- Safari не имеет тайм-аута (или, по крайней мере, ничего, кроме базового тайм-аута сети).
Что еще хуже, разработчики имеют ограниченный контроль над принятием решения о том, как эти правила повлияют на их приложение. Разработчик, ориентированный на производительность, может предпочесть иметь более быстрый начальный опыт с использованием резервного шрифта и использовать более удобный веб-шрифт только при последующих посещениях после того, как у него будет возможность загрузить. Используя такие инструменты, как Font Loading API, можно переопределить некоторые из поведения браузера по умолчанию и добиться повышения производительности, но это происходит за счет необходимости писать нетривиальные объемы JavaScript, которые затем должны быть встроены в страницу или запрашивается из внешнего файла, что вызывает дополнительную задержку HTTP.
Чтобы помочь исправить эту ситуацию, рабочая группа CSS предложила новый @font-face
дескриптор font-display
и соответствующее свойство для управления отображением загружаемого шрифта до его полной загрузки.
График загрузки шрифтов
Подобно существующему поведению при тайм-ауте шрифта, которое сегодня реализуют некоторые браузеры, font-display
время жизни загрузки шрифта делится на три основных периода.
- Первый период — период блока шрифта . В течение этого периода, если начертание шрифта не загружено, любой элемент, пытающийся его использовать, должен вместо этого визуализировать с невидимым резервным начертанием шрифта. Если начертание шрифта успешно загружается в течение периода блокировки, оно используется как обычно.
- Период смены шрифтов наступает сразу после периода блока шрифтов. В течение этого периода, если начертание шрифта не загружено, любой элемент, пытающийся его использовать, должен вместо этого визуализировать с резервным начертанием шрифта. Если начертание шрифта успешно загружается в течение периода подкачки, оно используется как обычно.
- Период сбоя шрифта наступает сразу после периода замены шрифта. Если начертание шрифта еще не загружено в начале этого периода, оно помечается как неудачная загрузка, вызывая нормальный откат шрифта. В противном случае начертание шрифта используется нормально.
Понимание этих периодов означает, что вы можете использовать их, font-display
чтобы решить, как ваш шрифт должен отображаться в зависимости от того, был ли он загружен или когда он был загружен.
Какой шрифт-дисплей вам подходит?
Для работы с font-display
дескриптором добавьте его в свои @font-face
правила:
1 2 3 4 5 6 |
@font-face { font-family: 'Arvo'; font-display: auto; src: local('Arvo'), url(https://fonts.gstatic.com/s/arvo/v9/rC7kKhY-eUDY-ucISTIf5PesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); } |
font-display
в настоящее время поддерживает следующий диапазон значений auto | block | swap | fallback | optional
.
Значение auto
Auto использует любую стратегию отображения шрифтов, которую использует пользовательский агент. Большинство браузеров в настоящее время имеют стратегию по умолчанию, аналогичную блокировке .
Значение block
Block дает шрифту короткий период блока (в большинстве случаев рекомендуется 3 секунды) и бесконечный период подкачки. Другими словами, браузер сначала рисует «невидимый» текст, если шрифт не загружен, но меняет лицевую сторону шрифта, как только он загружается. Для этого браузер создает анонимный шрифт с метриками, аналогичными выбранному шрифту, но со всеми глифами, не содержащими «чернил». Это значение следует использовать только в том случае, если для использования страницы требуется отрисовка текста с использованием определенного шрифта.
Значение SWAP
Swap дает шрифту нулевой второй период блока и бесконечный период подкачки. Это означает, что браузер сразу же рисует текст с запасным вариантом, если начертание шрифта не загружено, но меняет начертание шрифта, как только оно загружается. Как и в случае с блоком , это значение следует использовать только тогда, когда для страницы важен рендеринг текста с использованием определенного шрифта, но рендеринг с любым шрифтом по-прежнему будет отображать правильное сообщение. Текст логотипа — хороший кандидат на замену, поскольку отображение названия компании с использованием разумного запасного варианта приведет к передаче сообщения, но в конечном итоге вы будете использовать официальный шрифт.
Значение FALLback
Резервный режим дает шрифту чрезвычайно малый период блока (в большинстве случаев рекомендуется 100 мс или меньше) и короткий период подкачки (в большинстве случаев рекомендуется три секунды). Другими словами, начертание шрифта сначала отображается с запасным вариантом, если оно не загружено, но шрифт заменяется местами, как только он загружается. Однако, если пройдет слишком много времени, откат будет использоваться до конца жизни страницы. резервный вариант — хороший кандидат для таких вещей, как основной текст, где вы бы хотели, чтобы пользователь начал читать как можно скорее и не хотел мешать его работе, перемещая текст по мере загрузки нового шрифта.
Значение optional
Optional дает шрифту чрезвычайно малый период блока (в большинстве случаев рекомендуется 100 мс или меньше) и нулевой период подкачки. Подобно резервному варианту , это хороший выбор, когда загружаемый шрифт более удобен, но не критичен для работы. В необязательных листья значение его в браузер , чтобы решить , следует ли инициировать шрифт скачать, который он может выбрать не делать , или это может сделать это как низкий приоритет в зависимости от того, что он считает , что было бы лучше для пользователя. Это может быть полезно в ситуациях, когда у пользователя слабое соединение, и извлечение шрифта может быть не лучшим использованием ресурсов.
Правильный подбор опции работы сайта с шрифтами позволяет поддерживать быструю скорость загрузки сайта.
Тестирование воспринимаемой производительности
Итак, как мы можем проверить влияние этих различных font-display
настроек на воспринимаемую производительность страницы веб-сайта? Один из способов — просто обновить @font-face
правило, развернуть его, а затем запустить через WebPageTest. Это работает, но есть другой способ упростить этот рабочий процесс.
И это за счет использования функциональности WebPageTest «Inject Script» (на вкладке «Advanced») и использования API загрузки шрифтов CSS .
Здесь мы используем метод, очень похожий на то, что демонстрирует Энди Дэвис в своем блоге « Улучшение воспринимаемой производительности с помощью ссылки Rel = preconnect HTTP Header» .
Ниже вы можете найти упрощенный код, который можно использовать для этого, или в Gist, который можно найти здесь :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
(function(){ // this will trigger a font load var customFont1 = new FontFace('custom font name', 'url([FONT_URL_HERE])', { display: 'block', // display setting to test here weight: '700' // font-weight // other font properties here }); // IMPORTANT: add the font to the document document.fonts.add(customFont1); // monitor the font load (optional) customFont1.loaded.then((fontFace) => { // log some info in the console console.info('Font status:', customFont1.status); // optional // log some info on the WPT waterfall chart performance.mark('wpt.customFont1Loaded'); // optional }, (fontFace) => { // if there's an error, tell us about it console.error('Font status:', customFont1.status); // optional }); // repeat above for multiple fonts })(); |
Измените приведенный выше код и вставьте его в текстовое поле «Inject Script». Приведенный выше код будет вставлен на тестовую страницу перед выполнением теста и загрузит и определит новый шрифт (с тем же font-family
именем) с вашими обновленными настройками.
Ключ к тому, чтобы заставить это решение работать, — убедиться, что добавленный вручную шрифт добавляется после@font-face
регистрации шрифтов CSS . Поскольку приоритет одноименных шрифтов font-family
равен: побеждает последний добавленный. Это отражает CSS, например, если у вас есть два селектора с одинаковой специфичностью, тот, который идет последним, «перезаписывает» первый.
Давайте посмотрим на гипотетический график тестирования:
- Запускается WebPageTest, браузер согласовывает соединение с сервером и запрашивает HTML.
- HTML загружается и анализируется, запрашиваются другие ресурсы страницы, такие как CSS и JS.
- На этом этапе WPT внедряет JavaScript и выполняет его. Наш новый шрифт определяется и загружается с помощью API загрузки шрифтов.
- CSS загружается и анализируется, он также содержит
@font-face
правило с той же базовой информацией (имя шрифта, URL-адрес шрифта и т. Д.). FontFace
Объект и@font-face
является CSS-связным. При синтаксическом анализе CSS шрифт добавляется в конец списка (он последний), поэтому он имеет приоритет над шрифтом, добавленным вручную.- Страница загружается в обычном режиме, никаких изменений от внедренного скрипта не наблюдается.
Пункт 3 — это непредсказуемая часть этого процесса. Нет никаких временных гарантий, что внедренный скрипт будет запущен после загрузки / анализа CSS. Он может отличаться в зависимости от браузера и запускается, как только документ существует. Итак, если приведенный выше код не работает для вас при настройке вашего конкретного сайта, что еще вы можете попробовать?
Решения
Итак, я нашел два решения для устранения этой проблемы:
Заблокируйте шрифт CSS. Этот вариант далеко не идеален, но он работает. Если у вас есть @font-face
правила, определенные в их собственном отдельном файле CSS, вы можете просто использовать функциональность блока WebPageTest для блокировки шрифта CSS:
В этой ситуации происходит то, что наш сценарий внедрения создает все соответствующие FontFace
объекты, и они не теряют приоритет в соответствии с @font-face
правилами CSS. У этого метода есть несколько серьезных проблем:
- Что будет, если у вас много шрифтов? Вам необходимо воспроизвести их все в сценарии внедрения.
- А как насчет того, чтобы CSS вашего шрифта был объединен с другим CSS? По сути, вам нужно заблокировать все ваши страницы CSS.
Так что да, этот метод может работать, но он далек от совершенства.
Определить загрузку CSS
Отказ от ответственности : следующий метод работает, но загрузка веб-страницы является сложной и недетерминированной . Итак, то, что работает для одного запуска (как показано в тестах ниже), внезапно перестанет работать в других тестах, использующих тот же самый код. Метод блокировки CSS намного более предсказуем.
Я нашел лучший метод — это зацепиться за тот факт, что вы можете определить, когда файл CSS загружен, с помощью небольшого количества JavaScript. Для этого можно изменить сценарий инъекции. Вот Gist с измененным кодом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
(function(){ // create our custom link tag for the stylesheet var url = "https://www.example.com/static/app.css"; // IMPORTANT: this is the CSS file that contains your @font-face rules var head = document.getElementsByTagName('head')[0]; var link = document.createElement('link'); link.type = "text/css"; link.rel = "stylesheet" link.href = url; // append the stylesheet to the head head.appendChild(link); // wait for the CSS file to load before modifying the font setup link.onload = function () { // define our font face and modify the properties (will trigger a load) var customFont1 = new FontFace('nta', 'url([FONT_URL_HERE])', { display: 'swap', // display setting to test here weight: '700' // font-weight // other font properties here }); // IMPORTANT: add the modified font to the FontFaceSet document.fonts.add(customFont1); // monitor the font load (optional) customFont1.loaded.then((fontFace) => { // log some info in the console console.info('Font status:', customFont1.status); // optional // log some info on the WPT waterfall chart performance.mark('wpt.customFont1Loaded'); // optional }, (fontFace) => { // if there's an error, tell us about it console.error('Font status:', customFont1.status); // optional }); // repeat above for multiple fonts } })(); |
С помощью этого скрипта мы подключаемся к событию загрузки CSS, содержащему наши @font-face
правила (это важно). Итак, вот что происходит в браузере:
- Запускается WebPageTest, браузер согласовывает соединение с сервером и запрашивает HTML.
- HTML загружается и анализируется, запрашиваются другие ресурсы страницы, такие как CSS и JS.
- На этом этапе WPT внедряет JavaScript, и он может выполняться. Если это так, мы создаем копию
<link>
элемента, загружающего наш@font-face
CSS, и ждем, пока он загрузится. - CSS загружается и анализируется. Браузер создает
FontFace
объекты для@font-face
правил в CSS (связанных с CSS). - Срабатывает событие загрузки CSS, и наши пользовательские
FontFace
объекты добавляются кFontFaceSet
последним, поэтому они имеют приоритет над настройками шрифтов, связанных с CSS (например,font-display
свойством). - Страница загружается с нашими измененными настройками шрифта.
Вот и все. Быстрый способ проверить различные font-display
настройки на реальном веб-сайте и посмотреть результаты в WebPageTest.
Отладка запуска WebPageTest
Это действительно полезный совет от Энди Дэвиса, который я немного изменил для этих примеров. Если вы хотите увидеть, как выглядит консольный вывод для браузера в тесте. Вставьте следующий код в текстовое поле ‘Inject Script’:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// hijack the console.log method, allowing you to log all console massages window._consoleMessages = []; console.log = function(m){_consoleMessages.push(m)}; // specifically used for this font example to 'copy' the `FontFace` object function flatten(obj) { var result = {}; for(var key in obj) { result[key] = obj[key]; } return result; } |
Затем в поле «Специальные показатели» в разделе «Пользовательские» введите следующие данные:
1 2 3 4 5 6 7 8 9 |
[consoleMessages] for(var font of document.fonts){ // push results into the hijacked console // could easily return a simple array though if required console.log(flatten(font)); } return JSON.stringify(_consoleMessages, null, 2); |
Это даст вам результат, похожий на этот:
Очень полезно, если вы ищете конкретную информацию о браузере во время тестового запуска.
Посмотрим на это в действии
Я создал очень простой набор страниц, чтобы продемонстрировать эту технику. Также есть небольшая информация о том, что печатается console
в браузерах, поддерживающих API. Если вы знакомы с DevTools, просто откройте их, и вы увидите информацию в консоли. Я создал 4 тестовых страницы:
- Стандартная страница с одним веб-шрифтом, загруженным с помощью
@font-face
правила CSS . Это наша ссылка control (font-display: auto
) . - Стандартная страница + тот же веб-шрифт, добавленный второй раз с помощью API загрузки шрифтов, с
font-display: swap
установленной ссылкой . - Стандартная страница + тот же веб-шрифт, добавленный второй раз с помощью API загрузки шрифтов, с
font-display: fallback
установленной ссылкой . - Стандартная страница + тот же веб-шрифт, добавленный второй раз с помощью API загрузки шрифтов, с
font-display: optional
установленной ссылкой .
Страницы 2, 3 и 4 являются доказательством правильности концепции. Каждый из них включает приведенный выше сценарий после fonts.css
файла. Таким образом, на этих страницах шрифт будет добавлен вручную FontFaceSet
вместе с новым font-display
свойством. Будет ли отображаться какие-либо изменения в WebPageTest? ПРИМЕЧАНИЕ . Веб-шрифт применяется только к заголовку (h1) на страницах, поэтому вам следует сосредоточиться на этом в следующих тестах.
Вы можете поближе взглянуть на сравнение 4 страниц здесь , но вот результаты, как я их вижу:
- Необязательно: заголовок отображается в начале с невидимым текстом-заполнителем. Через ~ 100 мс отображается резервный текст. Веб-шрифт никогда не отображается.
- Резерв: заголовок отображается в начале с невидимым текстом-заполнителем. Через ~ 100 мс отображается резервный текст. Шрифт загружается в течение 3 секунд, поэтому его заменяют.
- Swap: заголовок сразу загружается с видимым резервным шрифтом (например, период блока 0 с в действии). После загрузки резервный шрифт заменяется веб-шрифтом.
- Авто: Как и ожидалось, установлено значение
block
. Отображается невидимый текст-заполнитель, текст не отображается, пока не будет загружен веб-шрифт.
Все приведенные выше результаты являются ожидаемым результатом для каждого font-display
значения, и тот факт, что мы видим разницу, показывает, что шрифт, добавленный программно через API загрузки шрифтов CSS, может изменить страницу. Так что давайте сделаем еще один шаг. Давайте заставим WebPageTest внедрить скрипт за нас.
В этих тестах мы используем страницу управления во всех случаях, а затем заставляем WebPageTest вводить скрипт с каждым из различных font-display
значений. Полное сравнение результатов этих тестов можно увидеть здесь .
Он выглядит удивительно похожим на изображение выше, не так ли? Фактически, при ближайшем рассмотрении мы видим точно такие же результаты, как указано выше, для наших вручную введенных страниц сценария. Таким образом, мы можем использовать WebPageTest для изменения font-display
свойства страниц (и действительно любого свойства, которое не только для чтения ). Я уверен, что другие могут придумать и другие варианты использования этой техники.
статьи можно дополнить информацией о том, как улучшить производительность загрузки шрифтов на сайте:
1. Оптимизация шрифтов: перед загрузкой шрифтов на сайт, их можно оптимизировать с помощью различных инструментов. Удаление ненужных символов, сжатие файлов и использоавние субсетов шрифта помогут сократить размер файлов и ускорить их загрузку.
2. Ленивая загрузка шрифтов: можно применить технику ленивой загрузки шрифтов, при которой шрифты будут загружаться только в том случае, если они действительно используются на странице. Для этого можно использовать JavaScript и CSS.
3. Кеширование шрифтов: использование кэширования позволит браузеру сохранить загруженные шрифты и использовать их при последующих запросах к сайту. Это позволит уменьшить время загрузки шрифтов при повторных посещениях страницы.
4. Загрузка шрифтов из локального хранилища: если шрифты используются на нескольких страницах сайта, их можно загрузить один раз и сохранить в локальном хранилище браузера. При последующих запросах к сайту, шрифты будут загружаться из локального хранилища, что значительно ускорит их загрузку.
5. Минимизация количества используемых шрифтов: использование большого количества различных шрифтов на сайте может замедлить его загрузку. Лучше выбрать несколько основных шрифтов и использовать их на всех страницах сайта.
Внедрение этих рекомендаций поможет ускорить загрузку шрифтов на сайте и улучшить общую производительность сайта.
статьи упоминается, что новый дескриптор отображения шрифтов @font-face позволяет разработчикам решать, как их веб-шрифты будут отображаться (или откладываться) в зависимости от времени загрузки. Какие конкретные настройки и методы использования этого дескриптора рекомендует Google?
Какой дескриптор отображения шрифтов используется для настройки производительности сайта?