Для ускорения работы сайтов продолжается оптимизация шрифтов. Согласно данных HTTP Archive~37% топовых порталов на начало 2014 года использовали веб-шрифты, что обозначает двойной рост по сравнению с прошлым 12–месячным промежутком.

shrifty

Естественно, для большинства это не является сюрпризом.

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

Но, как обстоит ситуация со скоростью отрисовки? Не оказывает ли отрицательное влияние использование веб-шрифтов на производительность?

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

Приведем перечень факторов, которые определяют влияние веб-шрифтов на живость открытия страницы:

- число подключенных шрифтов и их уровень толщины;

- размер файлов применяемых шрифтов;

- темп передачи удаленных файлов;

- срок старта загрузки веб-шрифтов.

Два первых пункта находятся под контролем дизайнера портала. Чем больше будет использоваться различных шрифтов, тем больше запросов и переданных байтов.

Для ускорения загрузки необходимо уменьшить количество подключенных шрифтов до минимума.

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

Измерение задержки при загрузке шрифтов

Задержка во время передачи каждого конкретного файла шрифтов зависит, естественно, от его размера, который определяется количеством глифов, размером метаданных (к примеру, хинтинг для Windows-платформ) и применяемого метода компрессии.

Техники с использованием фрагментарного включения и UA-specific оптимизация тоже достаточно важны для приведения в норму размера передаваемых файлов.

Дополнительно к этому, поскольку мы обсуждаем вопрос задержек, имеет важное значение размещение файла шрифтов – то есть CDN оптимально подходит пользовательскому КЭШу.

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

Лучшим вариантом ответа на данный вопрос считается инструмент Resource Timing API, предоставляющий возможность получать временные данные DNS, TCP при передаче файлов для конкретного шрифта в отдельности. Совсем недавно Google Fonts внедрил поддержку Resource Timing.

Немного ниже приводится сниппет шифра, который замеряет задержку шрифтов в Google Analytics:

shrifty2

Вышеприведенный код делает замеры основных параметров для UA-оптимизированных веб-шрифтов и CSS-файлов.

Давайте посмотрим на данные для портала целиком в Google Analytics:

shrifty3

С точки зрения надежности, Resource Timing API специально не предоставляет материал об извлеченных из кэша шрифтах. Но мы можем узнать среднее значение, использовав в личной практике показатель 20 мс.

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

Взяв во внимание выше упомянутый факт и, основываясь на приведенных статистических данных посещений, получим средний период загрузки CSS-файла, который составляет около 100 мс.

При этом где-то 26% пользователей загружают его из местного кэша.

Затем необходимо загрузить требуемые файлы шрифтов, что по времени в среднем занимает <20мс – большая часть пользователей, уже их имеет в своем кэше браузера. Хорошая новость — замысел долго хранящихся и общих для всех порталов ресурсов шрифтов работает.

Достижения могут разниться в зависимости от применяемых шрифтов, типа, объема трафика и других переменных. Нет необходимости говорить о задержках и продуктивности веб-шрифтов общими терминами. У нас есть определенные инструменты и API для измерения всех этих значений. А то, что мы имеем возможность измерить, можем и оптимизировать.

Лимитирование времени загрузки медленных ресурсов шрифтов

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

В таком случае, критические ресурсы могут осуществлять блокировку отображения страницы, что еще в большей мере усугубит положение.

Для успешного противостояния различные браузеры используют всевозможные механизмы:

1.IE моментально отрисовывает текст с применением запасного шрифта и его перерисовывает, как только завершится загрузка основного;

2.Firefox ждет открытия оригинального файла шрифтов три секунды, после чего использует резервный вариант. После окончания загрузки основного – перерисовывает текст с его использованием;

3.Safari и Google Chrome не отрисовывают страницу до того времени, пока загрузка шрифта не завершится.

У каждого из вышеперечисленных вариантов есть положительные и отрицательные стороны. Вряд ли есть необходимость дискутировать на данную тему.

Большинство пользователей согласится, что отсутствие тайм-аута в Safari и Google Chrome — это не рациональный подход, и именно этим уже на протяжении некоторого времени занимается группа специалистов Google Chrome.

Каким должен быть оптимальный тайм-аут?

Чтобы дать ответ на вопрос, мы воспользовались Google Chrome для определения времени выбора шрифтов различного размера, что привело к следующим результатам:

shrifty4

Первая хорошая новость заключается в том, что большая часть веб-шрифтов небольшого размера (<50Кб).

А вторая – загрузка большого количества шрифтов заканчивается за промежуток в несколько сотен миллисекунд: установление тайм-аута в десять секунд оказывает влияние только на ~ 0.3% запросов при загрузке шрифтов, а промежуток в три секунды только на ~1.1%.
Опираясь на эти данные, можно сделать вывод, что наилучшим решением для Google Chrome было бы копирование поведения Firefox: тайм-аут после трех секунд, затем применение запасного шрифта, а позже открытие основного – перерисовка с его участием.

Такое поведение планируют реализовать в Google Chrome M35 и, надеемся, что разработчики Safari поступят аналогично.

Практическая деятельность: инициализация запроса при загрузке сайта

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

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

Рассмотрим следующий пример:

shrifty5

В этом небольшом коде происходит многое: у нас имеются внешние CSS-и JavaScript- файлы и inline-блок с некоторыми строками CSS, которые включают два объявления шрифтов.
Предмет обсуждения заключается в том, когда запрос шрифта будет инициироваться браузером?

Давайте все пошагово разберем:

1.Парсер документа занимается поиском внешнего файла stylesheet.css и отправляется запрос;

2.Парсер документа проходит обработку inline-блоком с CSS-кодом, где объявлен шрифт FontA.

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

3.Парсер документа блокируется с помощью внешнего скрипта: нельзя продолжать до того времени, пока загрузка не завершится;

4.После того как загрузка скрипта запустится и сформируется окончательное DOM-дерево, делается просчет стилей, и осуществляется позиционирование блоков, после чего отправляется запрос загрузки fontA.

Именно в этот момент уже можно начать отрисовку, но текст с применением указанного шрифта пока не сможет быть выведен, так как файл все еще проходит этап загрузки…

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

С одной стороны хорошо, так как минимизируется количество загрузок.

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

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

Для исправления этого момента есть несколько методов:

a) убрать JavaScript-шифр;

b)внести атрибут async для несинхронной загрузки скрипта;

c) перенести вниз страницы подключение скриптов.

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

Рекомендация: для дополнения к измерению задержек запросов для конкретного ресурса мы можем вычислить и сделать анализ начального времени запроса с использованием Resource Timing.

Контроль за этим значением позволит определить, когда именно запросили загрузку шрифта.

Проведение оптимизации шрифтов в Google Chrome M33

Специалисты сделали правильный оптимизационный шаг, который позволил значительно улучшить производительность рендеринга шрифтов.

Для понимания, что конкретно было сделано, посмотрим на временную шкалу данных процесса обработки страницы в Google Chrome версии pre-M33, которая это хорошо иллюстрирует:

shrifty6

- вычисление стилей для страницы был закончен за ~840 мс;

- запущено позиционирование блоков по истечении ~1040 мс с момента старта обработки страницы. После этого, почти моментально начал инициироваться запрос ресурса шрифта.

Зачем нужно ожидать выполнение позиционирования, если расчет стилей произведен ранее 200 мс?

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

На первый взгляд, такой оптимизационный ход может показаться не очень значимым, но основываясь на замерах при помощи Google Chrome период между расчетом стилей и позиционированием блоков реально больше, чем можно предположить:

shrifty7

Запуская запрос для скачивания шрифтов сразу после расчета 1-го стиля, мы имеем возможность экономить около 130 мс.

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

Естественно, можно задать вполне очевидный вопрос: По какой причине задержка между позиционированием блоков и расчетом стилей настолько велика? Давайте начнем с Google Chrome DevTools: обратите внимание на временную линейку и определите наиболее медленные операции (например, долго выполняющиеся скрипты). Затем, если чувствуете желание, то наберите в chrome://tracing, чтобы посмотреть, что на самом деле происходит. Возможно, браузер занят обработкой блоков.

Оптимизация шрифтов при помощи Font Load Events API

Это API позволит нам определять и управлять, каким образом и когда будут загружены шрифты. Можно планировать загрузку шрифтов, а также вычислять, как и когда шрифт будет отображен.
Если вы знаете JS-библиотеку Web Font Loader, то рассматривайте данный API как подобный, но более встроенный в браузер:
shrifty8

Font Load Events API обеспечивает абсолютный контроль над тем, какие применяются шрифты и, когда они «подгрузятся» (должны ли они осуществлять блокировку визуализации), а также когда они скачиваются.

В рассмотренном варианте мы создали объект FontFace в коде JavaScript и вызвали моментальную загрузку шрифта. Можно вставить сниппет в верхнюю часть страницы и абсолютно избежать блокировки CSSOM- и DOM деревьев.

Поэкспериментируйте с API в Google Chrome Canary – специальной версией для разработчиков. В том случае, если все пойдет хорошо, то реализуйте в стабильной версии M35.

Сделаем выводы

Веб-шрифты дают достаточно много преимуществ: лучшее качество читаемости и доступности.
Все это обеспечивает отличные результаты. Вопрос заключается не в том, применять ли веб-шрифты в ущерб продуктивности, а в том, чтобы грамотно их оптимизировать.

Давайте сделаем заключительный список этапов оптимизации:

- проверьте использование веб-шрифтов и уберите те, от которых лучше отказаться;

- удостоверьтесь, что ресурсы шрифтов оптимизированы;

-выполните замеры ресурсов шрифтов при помощи Resource Timing: с применением пункта «measure; optimize»;

- сделайте оптимизацию задержки передачи и времени инициализации запроса при загрузке каждого шрифта;

- подкорректируйте критический путь рендеринга, удалите лишние JS-скрипты;

- потратьте немного времени на то, чтобы провести эксперименты с Font Load Events API.

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