В последние несколько недель, по стечению обстоятельств на работе и в сторонних проектах, я узнал много о веб-шрифтах, а также много нового о Google Fonts в частности. Благодаря этому я могу дать более развернутый ответ на вопрос, который в прошлом мне казался простым: стоит ли вам хранить Google Fonts на своём сервере?
Говоря объективно, признаю, шрифты — не моя сильная сторона. Я предпочитаю более практичный подход и не зацикливаюсь на дизайне (посмотрите на этот сайт и убедитесь, что так и есть) и прежде не чувствовал необходимости в использовании нестандартных шрифтов. Конечно, они выглядят немного приятнее и «брендируют» текст. Но для основного текста толку в них мало. Я никогда не оценивал статью (или иначе относился к её содержанию), только потому что для её подачи использовался красивый шрифт. Тем не менее, мне было полностью понятно негативное влияние дополнительных шрифтов на производительность и скорость загрузки страницы, так что, возможно, из-за этого я предвзят.
Тем не менее, многие со мной могут не согласится, да и шрифты, важны они лично для меня или нет, регулярно используются многими другими разработчиками, и часто у них просто нет выбора. Давайте посмотрим, что можно сделать, чтобы и в скорости сайта не потерять, и дизайнеров довольными оставить.
Несколько лет назад считалось нормой использовать CDN для подключения общих ресурсов (например, jQuery с code.jquery.com — и да, им до сих пор очень даже пользуются). Чтобы внести ясность, под CDN здесь я имею в виду загрузку ресурсов с чужого домена, а не ваш собственный CDN.
Причиной было то, что браузеры якобы ограничивали количество соединений с каждым доменом (обычно до 6 соединений), поэтому использование другого домена давало вам ещё 6 соединений. Это могло быть правдой в прошлом (особенно когда ограничение было <6 доменов) и до того, как HTTPS стал нормой, существенно увеличив затраты на соединение. Кроме того, HTTP/2 на самом деле выигрывает от использования одного соединения (в основном!), поэтому использование других доменов — чаще потеря в производительности, а не приобретение.
Ещё одним способом добиться того же был шардинг основного домена одним или несколькими техническими поддоменами (например, assets.example.com), и в этом случае шрифты опять же не размещаются на вашем основном домене, откуда загружается ваша веб-страница. Тем не менее, у данного способа те же проблемы с подключением, так что и это нельзя назвать выигрышем в производительности, даже если когда-то так и было.
Другим преимуществом публичного CDN считалась высокая вероятность того, что у посетителей уже есть эта версия условного jQuery в кэше. Но, опять же, я убежден, что это перебор. Существует очень много библиотек и их версий, а кэш браузера меньше, чем могло бы показаться, так что такое совпадение очень маловероятно. Кроме того, в Safari используется уникальный кэш HTTP на каждый посещённый домен, по соображениям конфиденциальности (double-keyed cache), и в Chrome эту функцию тоже скоро введут. Таким образом, здесь больше не о чем спорить.
Эта тема плавно переходит в разговор о влиянии сторонних CDN на конфиденциальность. Вы понятия не имеете, как и зачем они отслеживают ваших пользователей, чего не может произойти с self-hosted решением. А недавние нововведения в законодательстве обязывают многие сайты явно перечислять все cookies, используемые на сайте. Не самая простая задача при использовании сторонних CDN.
Уже долгое время я убежден, что сторонние CDN или даже шардинг ваших собственных доменов очень далеки от обещанного прироста производительности. Слишком часто можно встретить сайты, на которых основной домен раздаёт только index.html, а затем тратится куча времени впустую на установку новых соединений.
Это не говоря уже о последствиях загрузки ресурсов со сторонних сайтов для безопасности. Да, есть SRI, но это может вызвать неожиданные проблемы, и я, честно говоря, не вижу в этом смысла. Если это статический ресурс (где можно использовать SRI), то храните его локально, а если он не статический (потому что содержимое может измениться), то вы не можете использовать SRI.
Также, использование ресурсов из сторонних источников грозит тем, что они станут единой точкой сбоя (SPOF) и выведут ваш сайт из строя. Подобное случалось не раз, и хотя может показаться маловероятным, что Google Fonts упадёт, он может быть заблокирован прокси-серверами компании или целыми странами.
В целом, всё больше и больше людей советуют хранить свои статические ресурсы у себя, в идеале на домене, с которого вы раздаёте веб-страницы. Шрифты — это статические ресурсы, поэтому их касается то же самое, не так ли? Ну, оказывается, всё не так просто, потому что у шрифтов есть свои особенности и техники оптимизации, что может сделать локальное хранение немного сложнее…
Google Fonts — потрясающий ресурс, если вы любите шрифты. 977 свободных шрифтов, которые любой может использовать совершенно бесплатно. Коммерческие шрифты, зачастую, смехотворно дороги и обычно лицензируются, а не продаются, то есть плата взимается в зависимости от ожидаемого количества просмотров страницы. Поэтому иметь столько бесплатных и столь удобных в использовании шрифтов в одной коллекции — очень полезно.
Но и это ещё не всё. Google Fonts, как и многие провайдеры ресурсов для сайтов (см. пример jQuery выше), предоставляет CDN и хранит шрифты у себя давая возможность использовать их всем желающим непосредственно со своих серверов. Это означает, что вы можете начать использовать шрифты, просто добавив одну строку кода на вашем сайте, чтобы подгрузить таблицу стилей:
Вы также можете добавить больше свойств и шрифтов в одну строку, чтобы загрузить несколько шрифтов и вариаций каждого из них:
Недостаток — падение производительности (преимущество — тоже в производительности, но это не так очевидно, до этого мы дойдем). Проблема в том, что ваш сайт (скажем, www.example.com) загружает таблицу стилей с fonts.googleapis.com, которая возвращает некоторый CSS с правилами font-facе. Вот исходник по ссылке в примере выше:
О том, что означают некоторые из этих настроек, мы поговорим позже (а также о том, почему существует два правила font-face), но пока это означает, что вы можете использовать этот шрифт в своих стилях вот так:
Однако теперь вы должны подключиться к fonts.googleapis.com, скачать CSS, а затем подключиться к fonts.gstatic.com и скачать сами шрифты (почему Google не может разместить как CSS, так и шрифты на одном домене — искренне не понимаю!).
Шрифты часто обнаруживаются браузером с задержкой при загрузке страницы (ведь нужно загрузить CSS, чтобы найти ссылки на них). Но Google Fonts обнаруживаются ещё позже, потому что CSS нужно загрузить с другого домена, а затем шрифты с третьего домена и, как я уже упоминал, установление HTTPS-соединения тоже не мгновенное. Это можно увидеть на каскадной диаграмме ниже, сгенерированной WebPageTest (обратите внимание, что все тесты были запущены с Chrome — 3GSlow):
![](https://habrastorage.org/r/w1560/webt/94/si/uk/94siukfgpsuc3y8vvcenns7d8rm.png)
В строке 1 видно, что сначала загружается HTML. Затем, как только он загружен и прочитан чуть менее чем за 2 секунды, браузер обнаруживает необходимость загрузить CSS Google Fonts и загружает его в строке 4. Установка соединения занимает секунду, а затем 3,5 секунды скачивается файл. Наконец, браузер узнал о существовании нашего шрифта и загружает его в строке 6, потеряв по дороге ещё 1 ¼ секунды на соединение с fonts.gstatic.com.
Таким образом, использование этого шрифта от Google Fonts стоит нам целых трёх секунд производительности с момента доступности HTML, не учитывая времени на загрузку самого шрифта!
Можно ослабить этот ужасный удар по производительности при загрузке CSS и шрифтов с двух разных доменов. Первый домен (для CSS) следует расположить поближе к началу файла index.html, так чтобы браузер считал его поскорее, но второй всё ещё спрятан. Однако, мы-то знаем, каким будет этот домен (fonts.gstatic.com), поэтому можем открыть соединение заранее, чтобы сэкономить некоторое время на втором подключении позже:
При повторном тестировании видим следующую картину:
![](https://habrastorage.org/r/w1560/webt/0-/ab/1r/0-ab1rf2caybdrxaloc5xrs6d0k.png)
Здесь мы видим, что соединение на строке 5 открыто заранее, перед загрузкой CSS. Так мы выигрываем более одной секунды (загрузка шрифтов за 4 секунды, а не 5,25), потому что нам удалось избежать потери времени при установке соединения и шрифты скачиваются сразу же по факту прочтения CSS Google Fonts.
Вы могли бы подумать, что можно пойти дальше и предварительно загрузить весь шрифт, вместо того, чтобы довольствоваться только соединением с доменом, но Google Fonts называет шрифты уникальными хэшами. В приведённом выше примере загруженный шрифт называется S6uyw4BMUTPHjx4wXg.woff2, а не lato.woff2, поэтому предварительная загрузка невозможна, если только вы не хотите, чтобы ваш сайт упал в один прекрасный день, когда Google вдруг решит изменить этот хэш.
В любом случае, если вы используете Google Fonts и не намерены делать ничего другого после прочтения этой заметки, добавьте хотя бы предварительное подключение к домену, если его ещё нет. Это всего одна строчка кода и она должна заметно улучшить производительность вашей страницы.
Вообще-то, Google Fonts даёт похожую команду в HTTP заголовках, когда отдаёт CSS:
![](https://habrastorage.org/r/w1560/webt/1g/7n/lg/1g7nlg8c-qteofu6cr1t3eep2bi.png)
Но во многих случаях это не очень поможет, так как к моменту получения HTTP-заголовков ответа от сервера с CSS, браузер и так знает, что вы хотите подключиться к этому домену для загрузки шрифтов. Так что вам всё равно лучше указать это в HTML-коде, чтобы предварительная загрузка сработала раньше (не важно, что она таким образом дублируется, вторая попытка будет просто проигнорирована). Однако, если ваша страница всё еще обрабатывается ко времени получения заголовков от сервера CSS Google Fonts, и DOM не готов (может быть, это признак слишком большого количества JavaScript на вашей странице?), то это может помочь улучшить производительность, когда, наконец, выяснится, какой из шрифтов необходимо загрузить.
В приведённом выше коде font-face можно увидеть строку font-display: swap;. Это относительно новая инструкция. Её можно добавить к объявлению шрифта и она сообщит браузеру сначала использовать fallback, то есть системный шрифт (sans-serif в этом примере), а затем заменить его на реальный шрифт после его загрузки. Так можно избежать задержки в загрузке контента, когда шрифт ещё не прогрузился и тоже хорошо улучшить производительность.
Да, это приводит к вспышке нестилизированного текста (FOUT) — те самые «скачки» контента во время загрузки страницы, а некоторым это не нравится (моё мнение — согласен, контент более важен, чем стилизация, но прыгающий по всей странице текст раздражает, хоть это и можно смягчить, подправив запасной шрифт). Альтернативой является вспышка невидимого текста (FOIT). В таком случае, текст скрыт до тех пор, пока не появится шрифт, что, очевидно, задерживает загрузку и может вызвать другие проблемы, если какой-то текст загрузится, а какой-то нет!
В любом случае, до введения font-display: swap, разные браузеры справлялись с этим по-разному — некоторые, как IE и Edge, использовали FOUT, другие использовали FOIT, и у них было разное время до отказа от ожидания шрифтов. Из-за этого, если шрифт не загружался, ваш контент мог надолго остаться невидимым. Введение font-display: swap позволило разработчикам сайтов самим определять, как это будет происходить. Большинство браузеров поддерживают font-display: swap, за исключением IE и Edge, но, как указано выше, они используют это по умолчанию в любом случае. Шрифты Google также поддерживают различные варианты отображения шрифтов и предлагают font-display: swap по умолчанию.
Итак, еще один совет, если вы используете шрифты Google — проверить, что у вас есть параметр &display=swap в URL, и если нет (он только недавно стал поддерживаться), то добавить его:
Например, заменить это:
На это:
Вы также можете указать одно из других значений отображения шрифта, например, optional, если хотите.
К сожалению, это решает только половину проблемы. Эта инструкция находится в CSS, который возвращает Google Fonts, поэтому она полезна только после того, как вы скачали CSS-файл. Таким образом, это помогает справиться с задержкой во время загрузки самих шрифтов, но не помогает, пока вы ждете загрузки этого CSS. Так что это хорошее улучшение (по крайней мере, для тех, кто предпочитает FOUT), но всё же не всё решение в целом.
Я помогал создавать Web Almanac (фантастический взгляд на состояние интернета — посмотрите сами, если вы ещё не видели его) и медленная загрузка шрифтов Google на нашем сайте раздражала меня и я хотел это исправить. Особенно FOUT с font-display: swap. Мне было интересно, сможем ли мы уменьшить влияние этого, и естественным решением казалось локальное хранение файлов, возможно, с использованием предварительной загрузки.
Мы уже использовали вышеперечисленные приемы (предварительная загрузка и font-display: swap;), но, разумеется, было бы лучше вообще уйти от подключения CSS извне. Мы знаем, что будет в этом CSS. Стало быть, уверенно выбираем self-hosted? Вот здесь становится интересно…
Я нашёл на GitHub удобный скрипт (Google Font Download), который помог мне скачать все различные варианты шрифтов (так как их было много, до 9 в зависимости от страницы), а затем скопировал CSS, который он вывел в нашу главную таблицу стилей, и загрузил шрифты на сервер. Существуют и другие онлайн-инструменты, которые делают то же самое. Всё это, казалось, сработало, и мы избавились от раздражающей загрузки CSS и необходимости работы с двумя доменами.
Однако, при более внимательном осмотре я заметил, что шрифты были больше:
![](https://habrastorage.org/r/w1560/webt/1w/hk/fs/1whkfsun5mb15p76jzen2eft4wk.png)
Как вы можете видеть, произошло значительное увеличение размера (до 74% дополнительных для некоторых из них!) в сравнении загруженных шрифтов Google (справа) и локально размещенных шрифтов (слева). Изначально я думал, что это связано с моим локальным веб-сервером, например, из-за выключенного сжатия. Но шрифты WOFF2 обслуживаются без сжатия веб-сервером — или, по крайней мере, так должно быть — так как формат включает в себя сжатие Brotli. Также на скриншоте выше показаны загруженные байты (вверху чёрного цвета), а также несжатые байты (внизу чуть светлее) для каждого столбца (они достаточно похожи в обоих столбцах, так как шрифты действительно отдаются без сжатия веб-сервером, но загруженные байты включают заголовки HTTP, так что они немного больше), и были различия как в сжатых, так и в несжатых байтах, так что дело не в этом.
Сравнение правил font-face, полученных с помощью инструмента с оригинальными, выявило одно отличие:
Из Google Fonts:
Из инструмента для загрузки:
Первое отличие заключается в том, что мы потеряли строку font-display: swap, но это без проблем можно исправить. Куда более интересным является тот факт, что Google Fonts раздаёт два шрифта — и включает разные диапазоны Unicode в них. Это связано с font-subsetting и уменьшает файлы шрифтов.
Font subsetting — это удаление символов, которые вы не собираетесь использовать для уменьшения размера файла шрифта. Обычно большинство западных пользователей используют только латинские символы, и загрузка шрифта со всеми символами, которые вы, вероятно, не будете использовать, является нерациональной. Я слышал об этом раньше, но никогда не думал, насколько существенное влияние это может оказать! Google Fonts автоматически отдаёт font-face с набором символов латиницы, а также, где это возможно, подключит второй шрифт для символов расширенной латиницы (например, Ā), который будет загружен только при необходимости.
Фактически, вы можете также запросить специальный шрифт, содержащий только те символы, которые вам нужны с помощью параметра text:
https://fonts.googleapis.com/css?family=Lato&text=ABC
Судя по дальнейшим наблюдениям, инструмент для загрузки шрифтов, который я использовал, видимо, поддерживает font subsetting, но только для целого «языка» (латиница или расширенная латиница), и он объединил оба подмножества символов в один файл. В итоге я вернулся к использованию того, что использовал мой браузер, и перестал использовать этот инструмент. Это дало схожие размеры файлов (с небольшой разницей из-за HTTP-заголовков в моей среде разработки), но вскоре я обнаружил, что дело было не только в font subsetting.
Google Fonts не всегда отдает одинаковый CSS и зависит это от используемого user-agent. Например, для Internet Explorer 11 он отправляет следующее:
Здесь видно, что он предоставляет только формат WOFF, так как IE 11 не поддерживает WOFF2, и по той же причине не прописан unicode-range. Он отдает font-display: swap (как я и указал в URL для CSS), несмотря на то, что браузер не поддерживает его, но это и не вредит.
Дело не только в производителе и версии браузера. Font hinting включает в себя дополнительные инструкции в файле шрифта, которые затем используются для обеспечения наилучшего отображения шрифта — особенно на экранах с низким разрешением или для действительно маленьких размеров. Font hinting используется в Windows, но не в MacOS, поэтому в зависимости от того, с какой ОС вы работаете при получении шрифтов Google Fonts, при использовании браузера (даже если вы используете Chrome на каждой платформе), вы можете получить файлы шрифтов с хинтингом или без него. Если же вы загрузите версию для Windows и будете использовать её у себя, вы, фактически, заставите пользователей MacOS страдать от необходимости обрабатывать большие файлы шрифтов, полные неиспользуемого хинтинга, а если вы сделаете наоборот — вы потенциально заставите пользователей Windows страдать от худшего отображения шрифтов, без font hinting.
Когда я использовал Google Fonts, а также когда загружал шрифты для локального использования, я делал это на своем Mac, поэтому и получал файлы меньшего размера. Когда я использовал инструмент, я получал полные шрифты, с хинтингом. Так что это была ещё одна причина большой разницы в размерах!
Актуален ли по-прежнему font hinting, ведь экраны высокой четкости стали более распространёнными — это хороший вопрос, и многие шрифты изначально поставляются без хинтинга, поскольку на его создание уходит много времени. Когда он присутствуют — это может значительно увеличить размер шрифтов. В случае с Lato, размер удваивается. Стоит ли это дополнительной нагрузки, с которой вы столкнетесь, отказавшись от использования Google Fonts и разместив шрифты локально? Это ещё одно решение, которое вам нужно принять для себя самим.
Итак, Google Fonts CDN поддерживается умным скриптом, который отдаёт наиболее подходящие шрифты, оптимизируя их для сохранения максимальной производительности. Перейдя на локальное хранение шрифтов вам придётся настроить всё это самостоятельно, и есть вероятность потерять корректное отображение ваших шрифтов в некоторых браузерах, если этого не сделать.
Для Web Almanac мы посмотрели статистику по браузерам посетителей и приняли решение поддерживать только WOFF2, а также использовать версии MacOS без hinting, так как они вдвое меньше весят. Это упростило CSS (особенно с учётом того, что unicode-range поддерживается всеми браузерами, которые поддерживают WOFF2), а пользователи IE 11 и других старых браузеров по умолчанию видят sans-serif, который выглядит не очень хорошо, но на наш взгляд, шрифты — прогрессивное улучшение, и даже без них сайт всё ещё более чем пригоден для использования. Кроме того, более старые браузеры могут даже выиграть от использования системных шрифтов по умолчанию, так как они скорее всего будут использоваться на более старых, маломощных машинах.
Вы также можете внести и другие коррективы в используемые шрифты, если хотите (проверьте сначала лицензии!), но копирования шрифтов Google по умолчанию, используемых в Chrome на MacOS, вероятно, достаточно для большинства из нас, если вы хотите поддерживать только браузеры WOFF2 без hinting.
Тем не менее, если бы мы остановились на Google Fonts, то у нас был бы WOFF (и даже более старые форматы) и hinting где нужно, без необходимости глубокой настройки подстановки правильного шрифта в зависимости от браузера. Таким образом, у использования Google Fonts для шрифтов всё же есть определенные преимущества, и выбирая локальное хранение вы отказываетесь от них. Это касается и любых будущих усовершенствований Google Fonts.
Поскольку я углубился в тему шрифтов, и предупредил, что вы можете потерять любые будущие выгоды от Google Fonts перейдя на локальное хранение, хочу немного отойти от главной темы и рассказать о других интересных вещах, которые я обнаружил. Каковы предстоящие большие изменения в мире шрифтов? Ну, есть два изменения, которые активно обсуждаются в настоящее время и которые могут повлиять на шрифты в будущем (и, следовательно, могут быть поддержаны Google Fonts, возможно, по умолчанию, если вы выбрали использовать этот сервис): variable fonts и progressive font enrichment.
Variable fonts позволяют использовать различные стили шрифта без необходимости скачивания отдельных файлов. Ранее я упоминал, что в Web Almanac используется до 9 различных файлов шрифтов, но на самом деле это только 2 шрифта. Причина проста — на сайте также используется полужирный, курсив, жирный и даже тонкие версии одного или обоих из них. Так много вариаций одного и того же шрифта могут показаться неуместными и можно подумать, что браузер сам справится с задачей по изменению толщины текста или написания его курсивом. Да, это возможно. Но каждый браузер делает это немного по-разному, и результаты могут радикально отличаться, поэтому многие называют их «искусственными шрифтами».
Единственный способ обеспечить одинаковое отображение, это использовать «настоящий шрифт» специально для каждого начертания, которое вам нужно.
Variable fonts стандартизируют отображение различных вариаций шрифта и необходимость в дополнительных файлах пропадает. Теоретически, мы могли бы заменить эти 9 шрифтов на 2, когда станут доступны их variable font версии.
Это открывает массу возможностей использования шрифтов в интернете. Хотя мне может показаться, что 9 вариантов двух шрифтов — чересчур, на самом деле это не слишком много, в то время как variable fonts позволили бы бесконечные вариации. На мобильных устройствах вы можете задать немного другую толщину для «жирного», нежели на десктопах и планшетах. Variable fonts с несколькими простыми CSS инструкциями позволяют это без затрат ресурсов на загрузку дополнительного шрифта. Недавно на DotCSS Jason Pamental рассказал о variable fonts и продемонстрировал, как можно получить красиво оформленную страницу с, как кажется, большим количеством разных шрифтов — и всё это используя один файл!
Использование variable fonts также подразумевает одновременную загрузку всех вариаций шрифта, избегая путаницы, вызванной упомянутыми ранее проблемами. Это также приводит к меньшему количеству перерисовок макета: без variable fonts страница будет перерисовываться браузером снова и снова по мере загрузки каждого отдельного варианта шрифта.
Variable fonts имеют хорошую поддержку в современных браузерах, но их недостатком является большой размер, ведь для хранения различных вариаций шрифта требуется больше места, как и в случае с font hinting. Это зависит от шрифта, но обычно они в два раза больше после сжатия, поэтому чтобы оправдать их использование — вам должны быть необходимы как минимум два стиля. Даже в этом случае, возможно, вам лучше отдавать предпочтение одному файлу меньшего размера, загружаемому для отображения критически важного текста, а не одному файлу большего размера для отображения всего текста. И опять же, может использование font-display: swap будет менее проблематичным решением? Это решать каждому владельцу сайта самому!
Progressive Font Enrichment, по сути, выводит subsetting на новый уровень и позволяет загружать дополнительные определения символов по мере необходимости в виде потока дополнительной информации, которая дополняет загружаемый в настоящее время шрифт, а не добавляет дополнительный. Это может показаться небольшим преимуществом для нас, жителей Запада, но для других языков — особенно на Дальнем Востоке — файлы шрифтов могут быть весьма массивными (например, 2Mb), из-за огромного количества символов в этих языках. По этой причине веб-шрифты в таких странах используются реже и progressive font enrichment может положительно повлиять на ситуацию.
Progressive Font Enrichment, насколько я понял, находится на гораздо более ранней стадии, чем variable fonts, но есть онлайн-демонстрация. В любом случае, это еще одно потенциально интересное изменение, связанное со шрифтами.
Учитывая то, как работает Google Fonts, нетрудно представить, что он может и дальше обрастать новыми улучшениями, вроде описанных в данной статье (или многих других!), просто изменяя отдаваемый CSS. И он может это делать с умом. Например, определяя, поддерживает ли ваш браузер новую технологию (как он делает это сейчас с форматом шрифта — WOFF или WOFF2), или другими способами. Допустим, если вы запрашиваете более двух шрифтов, а отдавать variable font менее ресурсозатратно, то это можно автоматизировать и ссылаться на один и тот же файл шрифта в нескольких объявлениях font-face, а если вы запрашиваете только один вариант, то ссылаться на более легковесный, традиционный шрифт. Звучит надуманно? Они уже сделали это с одним шрифтом (Oswald)! Честно говоря, не знаю, возможно ли то же самое с Progressive Font Enrichment, так как не до конца понимаю принцип его работы, но будет интересно посмотреть.
Также, стоит упомянуть что используя Google Fonts, при обновлении шрифтов, например, для добавления новых наборов символов или исправления ошибок в глифах, вы получаете новые шрифты автоматически. При локальном хранении так не получится — по крайней мере, не без собственноручного вмешательства. Возможно, вы могли бы посмотреть в сторону проксирования запросов через ваш домен и таким образом взять лучшее из обоих вариантов, но это, скорее всего, всё равно будет медленнее и потребует дополнительной настройки и управления.
С другой стороны, локальное хранение обеспечивает стабильность, так как некоторые обновления могут повлиять на ваш дизайн, например, если заголовок в одну строку начинает растягиваться до двух из-за изменения шрифта. Есть категория людей, которые очень расстраиваются из-за этого
Итак, мы обсудили много теории, и хотя есть явные потенциальные преимущества от локального хранения, есть также сложности, которые необходимо учитывать, и поэтому использование Google Fonts также имеет некоторые явные выгоды. Так стоит self-hosted того? Это зависит от реальных удобств в конкретной ситуации. Если разница в производительности будет незначительной — возможно, стоит продолжить использовать Google Fonts, если большой — соответственно.
Для Web Almanac мы недавно выбрали локальное хранение Google Fonts, и тестирование показало резкие изменения:
![](https://habrastorage.org/r/w1560/webt/oa/xy/ha/oaxyhappghsnk9rj-l4qoicboki.png)
На нижнем изображении размещены локальные шрифты на нашем тестовом сервере, и вы можете видеть, что время загрузки сократилось вдвое — с 6 до 3 секунд! Проведя более глубокий анализ, я увидел, что производительность возросла даже больше (3 ⅓ секунды экономии)!
Что не так очевидно (но что мы увидим позже) — к этому моменту шрифты не загружены полностью ни на одном из изображений — при локальном хранении это занимает 7,5 секунд и 10,5 секунд при использовании Google Fonts. Однако используемые шрифты довольно похожи на стандартные, и особых скачков верстки не заметно. Это можно увидеть на диаграмме ниже:
![](https://habrastorage.org/r/w1560/webt/ai/zw/vu/aizwvu3sstjfwd68gd7gzhez4im.png)
На диаграмме видно, что страница с локальным хранением (красным цветом) почти полностью загружена за 2,4 секунды, а затем обновляется ещё несколько раз по мере загрузки изображений, после чего отображаются и шрифты. Да, мне бы хотелось сделать всё ещё более гладким, но всё же некоторые затраты на загрузку шрифтов оптимизировать невозможно.
Причина, по которой улучшения действительно ощутимы, заключается ещё в одной вещи, которую я сначала не учёл: CSS блокирует рендеринг. Так что при наличии ссылки на Google Fonts CSS, браузер не просто задерживает отображение текста — он задерживает отображение всего содержимого страницы! Шрифт — это прогрессивное улучшение, поэтому мы можем безопасно рендерить остальную часть страницы, и даже сам текст (со стандартными/fallback шрифтами), но браузер этого не делает — он просто видит, что есть какой-то CSS и пытается загрузить его, откладывая загрузку остальной страницы. Для CSS нет асинхронной загрузки — но, возможно, она должна быть для таких случаев? Всё же мы рискуем тем, что в случае проблем с подключением к Google Fonts, весь ваш сайт будет недоступен до тех пор, пока браузер не прекратит попытки обработать ссылку!
![](https://habrastorage.org/r/w1560/webt/v6/3_/oo/v63_oow5ktzvixadg7tpirrthcs.png)
На сравнительной диаграмме выше вертикальная зеленая линия Start Render происходит аж спустя 6 секунд — так как ей приходится ждать, пока Google Fonts CSS загрузится в строке 12, тратя половину времени на подключение к домену, а другую половину на фактическую загрузку.
Сравните это с локальной версией:
![](https://habrastorage.org/r/w1560/webt/x6/hm/4c/x6hm4c_omalxhr4ogx_5pueneci.png)
Здесь мы можем начать рендеринг, как только CSS сайта будет загружен и обработан за 2.5 секунды. Всё потому, что нет задержки подключения к домену Google Fonts.
В обоих случаях мы видим, что начало рендеринга происходит до загрузки шрифтов, и благодаря магии font-display: swap, текст всё ещё виден. Поэтому, по крайней мере, при использовании font-display: swap, было бы лучше, если бы Google Fonts не загружался с помощью CSS, блокирующего рендеринг, а, например, загружался через асинхронного JavaScript, который вставляет CSS шрифтов в страницу только после того, как они скачаны. Если бы процесс был реализован так, задержек рендера не происходило бы, правда, всё равно остаются задержки при соединении и долгое ожидание правильно отображаемого текста.
UPD: Я создал issue на GitHub Google Fonts с предложением добавить способ загрузки Google Fonts без блокировки рендера — голосуйте, если вы тоже этого хотите!
Zach Leatherman выступает за этот подход, чтобы уменьшить количество перерисовок, и показывает, что это также возможно с помощью одного только JavaScript, без необходимости использования CSS-файла. Затем он показывает другие преимущества управления вашими шрифтами с помощью JavaScript, например, вы можете отказаться от загрузки шрифтов вовсе, если сайт открыт из медленной сети (используя Network Information API), или если у пользователя включены настройки Save-Data или Prefers-Reduced-Motion. Интересные возможности!
После того, как вы отошли от хэшированных URL Google, у вас появляется возможность предварительно загрузить шрифт для дальнейшего повышения производительности. Однако, этот вариант имеет некоторые потенциальные недостатки, как обсуждал Andy Davies в статье Preloading Fonts and the Puzzle of Priorities. В основном, предварительно загружая шрифты и перемещая их вверх по очереди приоритетов, вы неявно понижаете приоритет других критических загрузок (например, CSS), а из-за ошибки в Chrome, шрифты могут даже прыгать выше некоторых из них.
Кроме того, предварительная загрузка, когда шрифт не будет использоваться, вызовет излишнюю неоправданную нагрузку — например, если локальная версия существует и может быть использована приоритетно, или если браузер не поддерживает данный формат шрифта (хотя все браузеры, которые поддерживают предварительную загрузку, также поддерживают WOFF2). Вместе с рекомендацией использовать предварительную загрузку, Google явно предупреждает вас об этом, и приятно видеть, что они обращают на это внимание.
При использовании функции font-display: swap, необходимость в предварительной загрузке может быть не такой сильной. Хотя в таком случае всё ещё можно выиграть время, загрузив минимально необходимое количество шрифтов и избегая таким образом FOUT и перерисовок. На данный момент мы не используем предварительную загрузку в Web Almanac и прежде чем начать, нам потребуется ещё несколько тестов, но пока что я доволен тем, что есть.
Отвечая на вопрос в названии статьи: да, стоит, так как прирост производительности существенен. Конечно, ваши результаты могут отличаться, ведь всё зависит от конкретного сайта, поэтому тестируйте, тестируйте, и ещё раз тестируйте. Но, я думаю, это всё же лучший вариант, с точки зрения производительности, для большинства сайтов.
Тем не менее, Google Fonts — это не просто хранилище сотен бесплатных шрифтов — это еще и умный механизм доставки, использующий многие из новейших техник оптимизации, чтобы отдавать наиболее подходящие шрифты с минимальными усилиями со стороны владельца сайта. Переходя на self-hosted, вам, в идеале, надо заново внедрить множество полезных улучшений, вроде font-display: swap, удаления font hinting (по крайней мере, для некоторых браузеров), или в противном случае вы можете наоборот, лишь навредить производительности тяжёлыми файлами шрифтов.
Это не самая лёгкая задача (а Google Fonts её делает за вас, да). Но поскольку сейчас использование только формата WOFF2 — единственная реалистичная опция, и браузеры хорошо поддерживают большинство техник оптимизации, всё стало намного легче, чем было раньше. Тем не менее, стоит иметь определённые знания о веб-шрифтах, прежде, чем всё это настраивать (надеюсь, этот пост в этом помог!), и заодно следить за новыми изменениями в мире шрифтов, так как там, несомненно, будут дальнейшие улучшения.
Ну, а может, мы слишком увлеклись оптимизацией и при локальном хранении можно позволить себе использовать полный шрифт, без subsetting и с hinting? На сайте Google Fonts есть возможность загрузить любой шрифт и делается это относительно просто, хотя странно, что архив не включает форматы WOFF и WOFF2 при использовании такого метода загрузки, что мне совершенно непонятно! Однако, если вы действительно заинтересованы в улучшении производительности (а вы должны быть заинтересованы!), то вам следует попробовать сделать дело правильно. Данная статья лишь показывает, что это немного сложнее, чем просто скачать и разместить шрифты на вашем сайте, как я всегда предполагал.
Вау, что-то текст оказался длиннее, чем я ожидал! Но, надеюсь, вам было так же, как и мне интересно разобраться в теме и у вас теперь есть пару новых идей по ускорению загрузки шрифтов на вашем сайте. Я настоятельно рекомендую вам подписаться на Jason и Zach в Твиттере, чтобы узнать больше полезного о шрифтах, а также на Andy, чтобы узнать больше о скорости веб-приложений в целом.
![](https://habrastorage.org/r/w1560/getpro/habr/post_images/9fa/cf4/a34/9facf4a348ef01048b4eb5e16ae66daa.png)
Говоря объективно, признаю, шрифты — не моя сильная сторона. Я предпочитаю более практичный подход и не зацикливаюсь на дизайне (посмотрите на этот сайт и убедитесь, что так и есть) и прежде не чувствовал необходимости в использовании нестандартных шрифтов. Конечно, они выглядят немного приятнее и «брендируют» текст. Но для основного текста толку в них мало. Я никогда не оценивал статью (или иначе относился к её содержанию), только потому что для её подачи использовался красивый шрифт. Тем не менее, мне было полностью понятно негативное влияние дополнительных шрифтов на производительность и скорость загрузки страницы, так что, возможно, из-за этого я предвзят.
Тем не менее, многие со мной могут не согласится, да и шрифты, важны они лично для меня или нет, регулярно используются многими другими разработчиками, и часто у них просто нет выбора. Давайте посмотрим, что можно сделать, чтобы и в скорости сайта не потерять, и дизайнеров довольными оставить.
Self-Hosted vs Внешние ресурсы
Несколько лет назад считалось нормой использовать CDN для подключения общих ресурсов (например, jQuery с code.jquery.com — и да, им до сих пор очень даже пользуются). Чтобы внести ясность, под CDN здесь я имею в виду загрузку ресурсов с чужого домена, а не ваш собственный CDN.
Причиной было то, что браузеры якобы ограничивали количество соединений с каждым доменом (обычно до 6 соединений), поэтому использование другого домена давало вам ещё 6 соединений. Это могло быть правдой в прошлом (особенно когда ограничение было <6 доменов) и до того, как HTTPS стал нормой, существенно увеличив затраты на соединение. Кроме того, HTTP/2 на самом деле выигрывает от использования одного соединения (в основном!), поэтому использование других доменов — чаще потеря в производительности, а не приобретение.
Ещё одним способом добиться того же был шардинг основного домена одним или несколькими техническими поддоменами (например, assets.example.com), и в этом случае шрифты опять же не размещаются на вашем основном домене, откуда загружается ваша веб-страница. Тем не менее, у данного способа те же проблемы с подключением, так что и это нельзя назвать выигрышем в производительности, даже если когда-то так и было.
Другим преимуществом публичного CDN считалась высокая вероятность того, что у посетителей уже есть эта версия условного jQuery в кэше. Но, опять же, я убежден, что это перебор. Существует очень много библиотек и их версий, а кэш браузера меньше, чем могло бы показаться, так что такое совпадение очень маловероятно. Кроме того, в Safari используется уникальный кэш HTTP на каждый посещённый домен, по соображениям конфиденциальности (double-keyed cache), и в Chrome эту функцию тоже скоро введут. Таким образом, здесь больше не о чем спорить.
Эта тема плавно переходит в разговор о влиянии сторонних CDN на конфиденциальность. Вы понятия не имеете, как и зачем они отслеживают ваших пользователей, чего не может произойти с self-hosted решением. А недавние нововведения в законодательстве обязывают многие сайты явно перечислять все cookies, используемые на сайте. Не самая простая задача при использовании сторонних CDN.
Уже долгое время я убежден, что сторонние CDN или даже шардинг ваших собственных доменов очень далеки от обещанного прироста производительности. Слишком часто можно встретить сайты, на которых основной домен раздаёт только index.html, а затем тратится куча времени впустую на установку новых соединений.
Это не говоря уже о последствиях загрузки ресурсов со сторонних сайтов для безопасности. Да, есть SRI, но это может вызвать неожиданные проблемы, и я, честно говоря, не вижу в этом смысла. Если это статический ресурс (где можно использовать SRI), то храните его локально, а если он не статический (потому что содержимое может измениться), то вы не можете использовать SRI.
Также, использование ресурсов из сторонних источников грозит тем, что они станут единой точкой сбоя (SPOF) и выведут ваш сайт из строя. Подобное случалось не раз, и хотя может показаться маловероятным, что Google Fonts упадёт, он может быть заблокирован прокси-серверами компании или целыми странами.
В целом, всё больше и больше людей советуют хранить свои статические ресурсы у себя, в идеале на домене, с которого вы раздаёте веб-страницы. Шрифты — это статические ресурсы, поэтому их касается то же самое, не так ли? Ну, оказывается, всё не так просто, потому что у шрифтов есть свои особенности и техники оптимизации, что может сделать локальное хранение немного сложнее…
Google Fonts и как они работают
Google Fonts — потрясающий ресурс, если вы любите шрифты. 977 свободных шрифтов, которые любой может использовать совершенно бесплатно. Коммерческие шрифты, зачастую, смехотворно дороги и обычно лицензируются, а не продаются, то есть плата взимается в зависимости от ожидаемого количества просмотров страницы. Поэтому иметь столько бесплатных и столь удобных в использовании шрифтов в одной коллекции — очень полезно.
Но и это ещё не всё. Google Fonts, как и многие провайдеры ресурсов для сайтов (см. пример jQuery выше), предоставляет CDN и хранит шрифты у себя давая возможность использовать их всем желающим непосредственно со своих серверов. Это означает, что вы можете начать использовать шрифты, просто добавив одну строку кода на вашем сайте, чтобы подгрузить таблицу стилей:
<link href="https://fonts.googleapis.com/css?family=Lato&display=swap" rel="stylesheet">
Вы также можете добавить больше свойств и шрифтов в одну строку, чтобы загрузить несколько шрифтов и вариаций каждого из них:
<link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i,900%7CPoppins:300,400,700,900&display=swap" rel="stylesheet">
Недостаток — падение производительности (преимущество — тоже в производительности, но это не так очевидно, до этого мы дойдем). Проблема в том, что ваш сайт (скажем, www.example.com) загружает таблицу стилей с fonts.googleapis.com, которая возвращает некоторый CSS с правилами font-facе. Вот исходник по ссылке в примере выше:
/* latin-ext */
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjxAwXiWtFCfQ7A.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wXiWtFCc.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
О том, что означают некоторые из этих настроек, мы поговорим позже (а также о том, почему существует два правила font-face), но пока это означает, что вы можете использовать этот шрифт в своих стилях вот так:
body {
font-family: 'Lato', sans-serif;
}
Однако теперь вы должны подключиться к fonts.googleapis.com, скачать CSS, а затем подключиться к fonts.gstatic.com и скачать сами шрифты (почему Google не может разместить как CSS, так и шрифты на одном домене — искренне не понимаю!).
Шрифты часто обнаруживаются браузером с задержкой при загрузке страницы (ведь нужно загрузить CSS, чтобы найти ссылки на них). Но Google Fonts обнаруживаются ещё позже, потому что CSS нужно загрузить с другого домена, а затем шрифты с третьего домена и, как я уже упоминал, установление HTTPS-соединения тоже не мгновенное. Это можно увидеть на каскадной диаграмме ниже, сгенерированной WebPageTest (обратите внимание, что все тесты были запущены с Chrome — 3GSlow):
![](https://habrastorage.org/webt/94/si/uk/94siukfgpsuc3y8vvcenns7d8rm.png)
В строке 1 видно, что сначала загружается HTML. Затем, как только он загружен и прочитан чуть менее чем за 2 секунды, браузер обнаруживает необходимость загрузить CSS Google Fonts и загружает его в строке 4. Установка соединения занимает секунду, а затем 3,5 секунды скачивается файл. Наконец, браузер узнал о существовании нашего шрифта и загружает его в строке 6, потеряв по дороге ещё 1 ¼ секунды на соединение с fonts.gstatic.com.
Таким образом, использование этого шрифта от Google Fonts стоит нам целых трёх секунд производительности с момента доступности HTML, не учитывая времени на загрузку самого шрифта!
Ускоряем Google Fonts предварительной загрузкой ресурсов
Можно ослабить этот ужасный удар по производительности при загрузке CSS и шрифтов с двух разных доменов. Первый домен (для CSS) следует расположить поближе к началу файла index.html, так чтобы браузер считал его поскорее, но второй всё ещё спрятан. Однако, мы-то знаем, каким будет этот домен (fonts.gstatic.com), поэтому можем открыть соединение заранее, чтобы сэкономить некоторое время на втором подключении позже:
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link href="https://fonts.googleapis.com/css?family=Lato&display=swap" rel="stylesheet">
При повторном тестировании видим следующую картину:
![](https://habrastorage.org/webt/0-/ab/1r/0-ab1rf2caybdrxaloc5xrs6d0k.png)
Здесь мы видим, что соединение на строке 5 открыто заранее, перед загрузкой CSS. Так мы выигрываем более одной секунды (загрузка шрифтов за 4 секунды, а не 5,25), потому что нам удалось избежать потери времени при установке соединения и шрифты скачиваются сразу же по факту прочтения CSS Google Fonts.
Вы могли бы подумать, что можно пойти дальше и предварительно загрузить весь шрифт, вместо того, чтобы довольствоваться только соединением с доменом, но Google Fonts называет шрифты уникальными хэшами. В приведённом выше примере загруженный шрифт называется S6uyw4BMUTPHjx4wXg.woff2, а не lato.woff2, поэтому предварительная загрузка невозможна, если только вы не хотите, чтобы ваш сайт упал в один прекрасный день, когда Google вдруг решит изменить этот хэш.
В любом случае, если вы используете Google Fonts и не намерены делать ничего другого после прочтения этой заметки, добавьте хотя бы предварительное подключение к домену, если его ещё нет. Это всего одна строчка кода и она должна заметно улучшить производительность вашей страницы.
Вообще-то, Google Fonts даёт похожую команду в HTTP заголовках, когда отдаёт CSS:
![](https://habrastorage.org/webt/1g/7n/lg/1g7nlg8c-qteofu6cr1t3eep2bi.png)
Но во многих случаях это не очень поможет, так как к моменту получения HTTP-заголовков ответа от сервера с CSS, браузер и так знает, что вы хотите подключиться к этому домену для загрузки шрифтов. Так что вам всё равно лучше указать это в HTML-коде, чтобы предварительная загрузка сработала раньше (не важно, что она таким образом дублируется, вторая попытка будет просто проигнорирована). Однако, если ваша страница всё еще обрабатывается ко времени получения заголовков от сервера CSS Google Fonts, и DOM не готов (может быть, это признак слишком большого количества JavaScript на вашей странице?), то это может помочь улучшить производительность, когда, наконец, выяснится, какой из шрифтов необходимо загрузить.
Font Display: Swap
В приведённом выше коде font-face можно увидеть строку font-display: swap;. Это относительно новая инструкция. Её можно добавить к объявлению шрифта и она сообщит браузеру сначала использовать fallback, то есть системный шрифт (sans-serif в этом примере), а затем заменить его на реальный шрифт после его загрузки. Так можно избежать задержки в загрузке контента, когда шрифт ещё не прогрузился и тоже хорошо улучшить производительность.
Да, это приводит к вспышке нестилизированного текста (FOUT) — те самые «скачки» контента во время загрузки страницы, а некоторым это не нравится (моё мнение — согласен, контент более важен, чем стилизация, но прыгающий по всей странице текст раздражает, хоть это и можно смягчить, подправив запасной шрифт). Альтернативой является вспышка невидимого текста (FOIT). В таком случае, текст скрыт до тех пор, пока не появится шрифт, что, очевидно, задерживает загрузку и может вызвать другие проблемы, если какой-то текст загрузится, а какой-то нет!
В любом случае, до введения font-display: swap, разные браузеры справлялись с этим по-разному — некоторые, как IE и Edge, использовали FOUT, другие использовали FOIT, и у них было разное время до отказа от ожидания шрифтов. Из-за этого, если шрифт не загружался, ваш контент мог надолго остаться невидимым. Введение font-display: swap позволило разработчикам сайтов самим определять, как это будет происходить. Большинство браузеров поддерживают font-display: swap, за исключением IE и Edge, но, как указано выше, они используют это по умолчанию в любом случае. Шрифты Google также поддерживают различные варианты отображения шрифтов и предлагают font-display: swap по умолчанию.
Итак, еще один совет, если вы используете шрифты Google — проверить, что у вас есть параметр &display=swap в URL, и если нет (он только недавно стал поддерживаться), то добавить его:
Например, заменить это:
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
На это:
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link href="https://fonts.googleapis.com/css?family=Lato&display=swap" rel="stylesheet">
Вы также можете указать одно из других значений отображения шрифта, например, optional, если хотите.
К сожалению, это решает только половину проблемы. Эта инструкция находится в CSS, который возвращает Google Fonts, поэтому она полезна только после того, как вы скачали CSS-файл. Таким образом, это помогает справиться с задержкой во время загрузки самих шрифтов, но не помогает, пока вы ждете загрузки этого CSS. Так что это хорошее улучшение (по крайней мере, для тех, кто предпочитает FOUT), но всё же не всё решение в целом.
Локальное хранение Google Fonts
Я помогал создавать Web Almanac (фантастический взгляд на состояние интернета — посмотрите сами, если вы ещё не видели его) и медленная загрузка шрифтов Google на нашем сайте раздражала меня и я хотел это исправить. Особенно FOUT с font-display: swap. Мне было интересно, сможем ли мы уменьшить влияние этого, и естественным решением казалось локальное хранение файлов, возможно, с использованием предварительной загрузки.
Мы уже использовали вышеперечисленные приемы (предварительная загрузка и font-display: swap;), но, разумеется, было бы лучше вообще уйти от подключения CSS извне. Мы знаем, что будет в этом CSS. Стало быть, уверенно выбираем self-hosted? Вот здесь становится интересно…
Я нашёл на GitHub удобный скрипт (Google Font Download), который помог мне скачать все различные варианты шрифтов (так как их было много, до 9 в зависимости от страницы), а затем скопировал CSS, который он вывел в нашу главную таблицу стилей, и загрузил шрифты на сервер. Существуют и другие онлайн-инструменты, которые делают то же самое. Всё это, казалось, сработало, и мы избавились от раздражающей загрузки CSS и необходимости работы с двумя доменами.
Однако, при более внимательном осмотре я заметил, что шрифты были больше:
![](https://habrastorage.org/webt/1w/hk/fs/1whkfsun5mb15p76jzen2eft4wk.png)
Как вы можете видеть, произошло значительное увеличение размера (до 74% дополнительных для некоторых из них!) в сравнении загруженных шрифтов Google (справа) и локально размещенных шрифтов (слева). Изначально я думал, что это связано с моим локальным веб-сервером, например, из-за выключенного сжатия. Но шрифты WOFF2 обслуживаются без сжатия веб-сервером — или, по крайней мере, так должно быть — так как формат включает в себя сжатие Brotli. Также на скриншоте выше показаны загруженные байты (вверху чёрного цвета), а также несжатые байты (внизу чуть светлее) для каждого столбца (они достаточно похожи в обоих столбцах, так как шрифты действительно отдаются без сжатия веб-сервером, но загруженные байты включают заголовки HTTP, так что они немного больше), и были различия как в сжатых, так и в несжатых байтах, так что дело не в этом.
Сравнение правил font-face, полученных с помощью инструмента с оригинальными, выявило одно отличие:
Из Google Fonts:
/* latin-ext */
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjxAwXiWtFCfQ7A.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wXiWtFCc.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
Из инструмента для загрузки:
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
src:
local('Lato Regular'),
local('Lato-Regular'),
/* from https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wXg.woff2 */
url('Lato_400.woff2') format('woff2'),
/* from https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wWA.woff */
url('Lato_400.woff') format('woff');
}
Первое отличие заключается в том, что мы потеряли строку font-display: swap, но это без проблем можно исправить. Куда более интересным является тот факт, что Google Fonts раздаёт два шрифта — и включает разные диапазоны Unicode в них. Это связано с font-subsetting и уменьшает файлы шрифтов.
Font Subsetting
Font subsetting — это удаление символов, которые вы не собираетесь использовать для уменьшения размера файла шрифта. Обычно большинство западных пользователей используют только латинские символы, и загрузка шрифта со всеми символами, которые вы, вероятно, не будете использовать, является нерациональной. Я слышал об этом раньше, но никогда не думал, насколько существенное влияние это может оказать! Google Fonts автоматически отдаёт font-face с набором символов латиницы, а также, где это возможно, подключит второй шрифт для символов расширенной латиницы (например, Ā), который будет загружен только при необходимости.
Фактически, вы можете также запросить специальный шрифт, содержащий только те символы, которые вам нужны с помощью параметра text:
https://fonts.googleapis.com/css?family=Lato&text=ABC
Судя по дальнейшим наблюдениям, инструмент для загрузки шрифтов, который я использовал, видимо, поддерживает font subsetting, но только для целого «языка» (латиница или расширенная латиница), и он объединил оба подмножества символов в один файл. В итоге я вернулся к использованию того, что использовал мой браузер, и перестал использовать этот инструмент. Это дало схожие размеры файлов (с небольшой разницей из-за HTTP-заголовков в моей среде разработки), но вскоре я обнаружил, что дело было не только в font subsetting.
Google Fonts «умно» раздаёт шрифты
Google Fonts не всегда отдает одинаковый CSS и зависит это от используемого user-agent. Например, для Internet Explorer 11 он отправляет следующее:
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wWA.woff) format('woff');
}
Здесь видно, что он предоставляет только формат WOFF, так как IE 11 не поддерживает WOFF2, и по той же причине не прописан unicode-range. Он отдает font-display: swap (как я и указал в URL для CSS), несмотря на то, что браузер не поддерживает его, но это и не вредит.
Дело не только в производителе и версии браузера. Font hinting включает в себя дополнительные инструкции в файле шрифта, которые затем используются для обеспечения наилучшего отображения шрифта — особенно на экранах с низким разрешением или для действительно маленьких размеров. Font hinting используется в Windows, но не в MacOS, поэтому в зависимости от того, с какой ОС вы работаете при получении шрифтов Google Fonts, при использовании браузера (даже если вы используете Chrome на каждой платформе), вы можете получить файлы шрифтов с хинтингом или без него. Если же вы загрузите версию для Windows и будете использовать её у себя, вы, фактически, заставите пользователей MacOS страдать от необходимости обрабатывать большие файлы шрифтов, полные неиспользуемого хинтинга, а если вы сделаете наоборот — вы потенциально заставите пользователей Windows страдать от худшего отображения шрифтов, без font hinting.
Когда я использовал Google Fonts, а также когда загружал шрифты для локального использования, я делал это на своем Mac, поэтому и получал файлы меньшего размера. Когда я использовал инструмент, я получал полные шрифты, с хинтингом. Так что это была ещё одна причина большой разницы в размерах!
Актуален ли по-прежнему font hinting, ведь экраны высокой четкости стали более распространёнными — это хороший вопрос, и многие шрифты изначально поставляются без хинтинга, поскольку на его создание уходит много времени. Когда он присутствуют — это может значительно увеличить размер шрифтов. В случае с Lato, размер удваивается. Стоит ли это дополнительной нагрузки, с которой вы столкнетесь, отказавшись от использования Google Fonts и разместив шрифты локально? Это ещё одно решение, которое вам нужно принять для себя самим.
Итак, Google Fonts CDN поддерживается умным скриптом, который отдаёт наиболее подходящие шрифты, оптимизируя их для сохранения максимальной производительности. Перейдя на локальное хранение шрифтов вам придётся настроить всё это самостоятельно, и есть вероятность потерять корректное отображение ваших шрифтов в некоторых браузерах, если этого не сделать.
Для Web Almanac мы посмотрели статистику по браузерам посетителей и приняли решение поддерживать только WOFF2, а также использовать версии MacOS без hinting, так как они вдвое меньше весят. Это упростило CSS (особенно с учётом того, что unicode-range поддерживается всеми браузерами, которые поддерживают WOFF2), а пользователи IE 11 и других старых браузеров по умолчанию видят sans-serif, который выглядит не очень хорошо, но на наш взгляд, шрифты — прогрессивное улучшение, и даже без них сайт всё ещё более чем пригоден для использования. Кроме того, более старые браузеры могут даже выиграть от использования системных шрифтов по умолчанию, так как они скорее всего будут использоваться на более старых, маломощных машинах.
Вы также можете внести и другие коррективы в используемые шрифты, если хотите (проверьте сначала лицензии!), но копирования шрифтов Google по умолчанию, используемых в Chrome на MacOS, вероятно, достаточно для большинства из нас, если вы хотите поддерживать только браузеры WOFF2 без hinting.
Тем не менее, если бы мы остановились на Google Fonts, то у нас был бы WOFF (и даже более старые форматы) и hinting где нужно, без необходимости глубокой настройки подстановки правильного шрифта в зависимости от браузера. Таким образом, у использования Google Fonts для шрифтов всё же есть определенные преимущества, и выбирая локальное хранение вы отказываетесь от них. Это касается и любых будущих усовершенствований Google Fonts.
Будущие усовершенствования Fonts
Поскольку я углубился в тему шрифтов, и предупредил, что вы можете потерять любые будущие выгоды от Google Fonts перейдя на локальное хранение, хочу немного отойти от главной темы и рассказать о других интересных вещах, которые я обнаружил. Каковы предстоящие большие изменения в мире шрифтов? Ну, есть два изменения, которые активно обсуждаются в настоящее время и которые могут повлиять на шрифты в будущем (и, следовательно, могут быть поддержаны Google Fonts, возможно, по умолчанию, если вы выбрали использовать этот сервис): variable fonts и progressive font enrichment.
Variable fonts
Variable fonts позволяют использовать различные стили шрифта без необходимости скачивания отдельных файлов. Ранее я упоминал, что в Web Almanac используется до 9 различных файлов шрифтов, но на самом деле это только 2 шрифта. Причина проста — на сайте также используется полужирный, курсив, жирный и даже тонкие версии одного или обоих из них. Так много вариаций одного и того же шрифта могут показаться неуместными и можно подумать, что браузер сам справится с задачей по изменению толщины текста или написания его курсивом. Да, это возможно. Но каждый браузер делает это немного по-разному, и результаты могут радикально отличаться, поэтому многие называют их «искусственными шрифтами».
Единственный способ обеспечить одинаковое отображение, это использовать «настоящий шрифт» специально для каждого начертания, которое вам нужно.
Variable fonts стандартизируют отображение различных вариаций шрифта и необходимость в дополнительных файлах пропадает. Теоретически, мы могли бы заменить эти 9 шрифтов на 2, когда станут доступны их variable font версии.
Это открывает массу возможностей использования шрифтов в интернете. Хотя мне может показаться, что 9 вариантов двух шрифтов — чересчур, на самом деле это не слишком много, в то время как variable fonts позволили бы бесконечные вариации. На мобильных устройствах вы можете задать немного другую толщину для «жирного», нежели на десктопах и планшетах. Variable fonts с несколькими простыми CSS инструкциями позволяют это без затрат ресурсов на загрузку дополнительного шрифта. Недавно на DotCSS Jason Pamental рассказал о variable fonts и продемонстрировал, как можно получить красиво оформленную страницу с, как кажется, большим количеством разных шрифтов — и всё это используя один файл!
Использование variable fonts также подразумевает одновременную загрузку всех вариаций шрифта, избегая путаницы, вызванной упомянутыми ранее проблемами. Это также приводит к меньшему количеству перерисовок макета: без variable fonts страница будет перерисовываться браузером снова и снова по мере загрузки каждого отдельного варианта шрифта.
Variable fonts имеют хорошую поддержку в современных браузерах, но их недостатком является большой размер, ведь для хранения различных вариаций шрифта требуется больше места, как и в случае с font hinting. Это зависит от шрифта, но обычно они в два раза больше после сжатия, поэтому чтобы оправдать их использование — вам должны быть необходимы как минимум два стиля. Даже в этом случае, возможно, вам лучше отдавать предпочтение одному файлу меньшего размера, загружаемому для отображения критически важного текста, а не одному файлу большего размера для отображения всего текста. И опять же, может использование font-display: swap будет менее проблематичным решением? Это решать каждому владельцу сайта самому!
Progressive Font Enrichment
Progressive Font Enrichment, по сути, выводит subsetting на новый уровень и позволяет загружать дополнительные определения символов по мере необходимости в виде потока дополнительной информации, которая дополняет загружаемый в настоящее время шрифт, а не добавляет дополнительный. Это может показаться небольшим преимуществом для нас, жителей Запада, но для других языков — особенно на Дальнем Востоке — файлы шрифтов могут быть весьма массивными (например, 2Mb), из-за огромного количества символов в этих языках. По этой причине веб-шрифты в таких странах используются реже и progressive font enrichment может положительно повлиять на ситуацию.
Progressive Font Enrichment, насколько я понял, находится на гораздо более ранней стадии, чем variable fonts, но есть онлайн-демонстрация. В любом случае, это еще одно потенциально интересное изменение, связанное со шрифтами.
Будет ли Google Fonts и далее совершенствоваться?
Учитывая то, как работает Google Fonts, нетрудно представить, что он может и дальше обрастать новыми улучшениями, вроде описанных в данной статье (или многих других!), просто изменяя отдаваемый CSS. И он может это делать с умом. Например, определяя, поддерживает ли ваш браузер новую технологию (как он делает это сейчас с форматом шрифта — WOFF или WOFF2), или другими способами. Допустим, если вы запрашиваете более двух шрифтов, а отдавать variable font менее ресурсозатратно, то это можно автоматизировать и ссылаться на один и тот же файл шрифта в нескольких объявлениях font-face, а если вы запрашиваете только один вариант, то ссылаться на более легковесный, традиционный шрифт. Звучит надуманно? Они уже сделали это с одним шрифтом (Oswald)! Честно говоря, не знаю, возможно ли то же самое с Progressive Font Enrichment, так как не до конца понимаю принцип его работы, но будет интересно посмотреть.
Также, стоит упомянуть что используя Google Fonts, при обновлении шрифтов, например, для добавления новых наборов символов или исправления ошибок в глифах, вы получаете новые шрифты автоматически. При локальном хранении так не получится — по крайней мере, не без собственноручного вмешательства. Возможно, вы могли бы посмотреть в сторону проксирования запросов через ваш домен и таким образом взять лучшее из обоих вариантов, но это, скорее всего, всё равно будет медленнее и потребует дополнительной настройки и управления.
С другой стороны, локальное хранение обеспечивает стабильность, так как некоторые обновления могут повлиять на ваш дизайн, например, если заголовок в одну строку начинает растягиваться до двух из-за изменения шрифта. Есть категория людей, которые очень расстраиваются из-за этого
Преимущества локального хранения шрифтов
Итак, мы обсудили много теории, и хотя есть явные потенциальные преимущества от локального хранения, есть также сложности, которые необходимо учитывать, и поэтому использование Google Fonts также имеет некоторые явные выгоды. Так стоит self-hosted того? Это зависит от реальных удобств в конкретной ситуации. Если разница в производительности будет незначительной — возможно, стоит продолжить использовать Google Fonts, если большой — соответственно.
Для Web Almanac мы недавно выбрали локальное хранение Google Fonts, и тестирование показало резкие изменения:
![](https://habrastorage.org/webt/oa/xy/ha/oaxyhappghsnk9rj-l4qoicboki.png)
На нижнем изображении размещены локальные шрифты на нашем тестовом сервере, и вы можете видеть, что время загрузки сократилось вдвое — с 6 до 3 секунд! Проведя более глубокий анализ, я увидел, что производительность возросла даже больше (3 ⅓ секунды экономии)!
Что не так очевидно (но что мы увидим позже) — к этому моменту шрифты не загружены полностью ни на одном из изображений — при локальном хранении это занимает 7,5 секунд и 10,5 секунд при использовании Google Fonts. Однако используемые шрифты довольно похожи на стандартные, и особых скачков верстки не заметно. Это можно увидеть на диаграмме ниже:
![](https://habrastorage.org/webt/ai/zw/vu/aizwvu3sstjfwd68gd7gzhez4im.png)
На диаграмме видно, что страница с локальным хранением (красным цветом) почти полностью загружена за 2,4 секунды, а затем обновляется ещё несколько раз по мере загрузки изображений, после чего отображаются и шрифты. Да, мне бы хотелось сделать всё ещё более гладким, но всё же некоторые затраты на загрузку шрифтов оптимизировать невозможно.
Причина, по которой улучшения действительно ощутимы, заключается ещё в одной вещи, которую я сначала не учёл: CSS блокирует рендеринг. Так что при наличии ссылки на Google Fonts CSS, браузер не просто задерживает отображение текста — он задерживает отображение всего содержимого страницы! Шрифт — это прогрессивное улучшение, поэтому мы можем безопасно рендерить остальную часть страницы, и даже сам текст (со стандартными/fallback шрифтами), но браузер этого не делает — он просто видит, что есть какой-то CSS и пытается загрузить его, откладывая загрузку остальной страницы. Для CSS нет асинхронной загрузки — но, возможно, она должна быть для таких случаев? Всё же мы рискуем тем, что в случае проблем с подключением к Google Fonts, весь ваш сайт будет недоступен до тех пор, пока браузер не прекратит попытки обработать ссылку!
![](https://habrastorage.org/webt/v6/3_/oo/v63_oow5ktzvixadg7tpirrthcs.png)
На сравнительной диаграмме выше вертикальная зеленая линия Start Render происходит аж спустя 6 секунд — так как ей приходится ждать, пока Google Fonts CSS загрузится в строке 12, тратя половину времени на подключение к домену, а другую половину на фактическую загрузку.
Сравните это с локальной версией:
![](https://habrastorage.org/webt/x6/hm/4c/x6hm4c_omalxhr4ogx_5pueneci.png)
Здесь мы можем начать рендеринг, как только CSS сайта будет загружен и обработан за 2.5 секунды. Всё потому, что нет задержки подключения к домену Google Fonts.
В обоих случаях мы видим, что начало рендеринга происходит до загрузки шрифтов, и благодаря магии font-display: swap, текст всё ещё виден. Поэтому, по крайней мере, при использовании font-display: swap, было бы лучше, если бы Google Fonts не загружался с помощью CSS, блокирующего рендеринг, а, например, загружался через асинхронного JavaScript, который вставляет CSS шрифтов в страницу только после того, как они скачаны. Если бы процесс был реализован так, задержек рендера не происходило бы, правда, всё равно остаются задержки при соединении и долгое ожидание правильно отображаемого текста.
UPD: Я создал issue на GitHub Google Fonts с предложением добавить способ загрузки Google Fonts без блокировки рендера — голосуйте, если вы тоже этого хотите!
Zach Leatherman выступает за этот подход, чтобы уменьшить количество перерисовок, и показывает, что это также возможно с помощью одного только JavaScript, без необходимости использования CSS-файла. Затем он показывает другие преимущества управления вашими шрифтами с помощью JavaScript, например, вы можете отказаться от загрузки шрифтов вовсе, если сайт открыт из медленной сети (используя Network Information API), или если у пользователя включены настройки Save-Data или Prefers-Reduced-Motion. Интересные возможности!
Предварительная загрузка шрифтов
После того, как вы отошли от хэшированных URL Google, у вас появляется возможность предварительно загрузить шрифт для дальнейшего повышения производительности. Однако, этот вариант имеет некоторые потенциальные недостатки, как обсуждал Andy Davies в статье Preloading Fonts and the Puzzle of Priorities. В основном, предварительно загружая шрифты и перемещая их вверх по очереди приоритетов, вы неявно понижаете приоритет других критических загрузок (например, CSS), а из-за ошибки в Chrome, шрифты могут даже прыгать выше некоторых из них.
Кроме того, предварительная загрузка, когда шрифт не будет использоваться, вызовет излишнюю неоправданную нагрузку — например, если локальная версия существует и может быть использована приоритетно, или если браузер не поддерживает данный формат шрифта (хотя все браузеры, которые поддерживают предварительную загрузку, также поддерживают WOFF2). Вместе с рекомендацией использовать предварительную загрузку, Google явно предупреждает вас об этом, и приятно видеть, что они обращают на это внимание.
При использовании функции font-display: swap, необходимость в предварительной загрузке может быть не такой сильной. Хотя в таком случае всё ещё можно выиграть время, загрузив минимально необходимое количество шрифтов и избегая таким образом FOUT и перерисовок. На данный момент мы не используем предварительную загрузку в Web Almanac и прежде чем начать, нам потребуется ещё несколько тестов, но пока что я доволен тем, что есть.
Заключение
Отвечая на вопрос в названии статьи: да, стоит, так как прирост производительности существенен. Конечно, ваши результаты могут отличаться, ведь всё зависит от конкретного сайта, поэтому тестируйте, тестируйте, и ещё раз тестируйте. Но, я думаю, это всё же лучший вариант, с точки зрения производительности, для большинства сайтов.
Тем не менее, Google Fonts — это не просто хранилище сотен бесплатных шрифтов — это еще и умный механизм доставки, использующий многие из новейших техник оптимизации, чтобы отдавать наиболее подходящие шрифты с минимальными усилиями со стороны владельца сайта. Переходя на self-hosted, вам, в идеале, надо заново внедрить множество полезных улучшений, вроде font-display: swap, удаления font hinting (по крайней мере, для некоторых браузеров), или в противном случае вы можете наоборот, лишь навредить производительности тяжёлыми файлами шрифтов.
Это не самая лёгкая задача (а Google Fonts её делает за вас, да). Но поскольку сейчас использование только формата WOFF2 — единственная реалистичная опция, и браузеры хорошо поддерживают большинство техник оптимизации, всё стало намного легче, чем было раньше. Тем не менее, стоит иметь определённые знания о веб-шрифтах, прежде, чем всё это настраивать (надеюсь, этот пост в этом помог!), и заодно следить за новыми изменениями в мире шрифтов, так как там, несомненно, будут дальнейшие улучшения.
Ну, а может, мы слишком увлеклись оптимизацией и при локальном хранении можно позволить себе использовать полный шрифт, без subsetting и с hinting? На сайте Google Fonts есть возможность загрузить любой шрифт и делается это относительно просто, хотя странно, что архив не включает форматы WOFF и WOFF2 при использовании такого метода загрузки, что мне совершенно непонятно! Однако, если вы действительно заинтересованы в улучшении производительности (а вы должны быть заинтересованы!), то вам следует попробовать сделать дело правильно. Данная статья лишь показывает, что это немного сложнее, чем просто скачать и разместить шрифты на вашем сайте, как я всегда предполагал.
Вау, что-то текст оказался длиннее, чем я ожидал! Но, надеюсь, вам было так же, как и мне интересно разобраться в теме и у вас теперь есть пару новых идей по ускорению загрузки шрифтов на вашем сайте. Я настоятельно рекомендую вам подписаться на Jason и Zach в Твиттере, чтобы узнать больше полезного о шрифтах, а также на Andy, чтобы узнать больше о скорости веб-приложений в целом.
![](https://habrastorage.org/getpro/habr/post_images/9fa/cf4/a34/9facf4a348ef01048b4eb5e16ae66daa.png)