До свидания, Google Fonts. Последний аргумент
Шрифты Google Fonts страшно популярны. Их загружают более 42,8 миллиона сайтов, в том числе Хабр. Библиотека Google Fonts содержит 1023 свободных шрифта и программные интерфейсы для их внедрения через CSS. Очень удобно, казалось бы.
Во многих статьях отмечалось, в какую цену обходятся многочисленные запросы через API. Совет самостоятельно хостить шрифты дают много лет. Даже сама Google давала такой совет на конференции Google I/O 2018 года в выступлении на тему веб-производительности.
Так почему же многие до сих пор загружают шрифты через Google Fonts API? Ну, был последний аргумент — кэширование. Мол, благодаря общему CDN пользователю не нужно скачивать шрифт заново с каждого сайта. Однако в октябре 2020 года этот аргумент перестал работать. Теперь шрифты Google Fonts больше не кэшируются!
По своей природе Google Fonts даже со всеми оптимизациями не может загружаться клиенту быстрее, чем с родного хостинга. Сравнительные бенчмарки можно посмотреть, например, здесь и здесь.
Загрузка Google Fonts без preconnect
Оптимизированная загрузка Google Fonts с опцией preconnect (подсказка для браузера заранее подключиться к домену fonts.gstatic.com, чтобы ускорить установку соединения в будущем):
Загрузка Google Fonts с preconnect
Дело в том, что Google всегда запрашивает с сервера таблицу стилей:
Она загружается любом случае. А уже потом декларация @font-face
говорит браузеру использовать локальную (кэшированную) версию шрифта при наличии таковой. По крайней мере, так было раньше:
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.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;
}
Но в последнее время Google удалила фунцию local()
из @font-face
в Google Fonts! То есть шрифты Google Fonts теперь не могут считываться локально, если использовать API.
Из-за дополнительных запросов в к серверу Google возникает лишняя задержка.
Загрузка с fonts.gstatic.com с опцией preconnect
Загрузка со своего хостинга с опцией preload
Как видим, во втором случае запросы к fonts.gstatic.com отсутствуют, что сразу сокращает время загрузки страницы. Это самый оптимальный вариант.
Марио Ранфтль создал очень полезный справочник google-webfonts-helper. Здесь можно выбрать конкретные шрифты из библиотеки Google Fonts, нужные наборы символов, начертания, посмотреть поддержку в браузерах — и получить код CSS и непосредственно сами файлы. То есть можно перенести нужные шрифты на свой хостинг в пару нажатий кнопки мыши.
Выбираем шрифт, наборы символов и стили. Чем больше стилей мы выберем, тем больше объём скачивания для клиента.
У разных семейств шрифтов разные уровни проработки. Например, кириллицу поддерживают только 118 из 1023 шрифтов на Google Fonts. Не все шрифты поддерживают полный набор начертаний.
Самое популярное в коллекции Google Fonts семейство шрифтов Roboto
И получаем код CSS для вставки. Вариант для поддержки максимальным количеством браузеров, в том числе устаревшими:
/* roboto-regular - latin_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url('../fonts/roboto-v20-latin_cyrillic-regular.eot'); /* IE9 Compat Modes */
src: local(''),
url('../fonts/roboto-v20-latin_cyrillic-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('../fonts/roboto-v20-latin_cyrillic-regular.woff2') format('woff2'), /* Super Modern Browsers */
url('../fonts/roboto-v20-latin_cyrillic-regular.woff') format('woff'), /* Modern Browsers */
url('../fonts/roboto-v20-latin_cyrillic-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('../fonts/roboto-v20-latin_cyrillic-regular.svg#Roboto') format('svg'); /* Legacy iOS */
}
Вариант для поддержки только современными браузерами:
/* roboto-regular - latin_cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local(''),
url('../fonts/roboto-v20-latin_cyrillic-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('../fonts/roboto-v20-latin_cyrillic-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
Как видим, здесь функция local()
сохранилась, в отличие от официальных стилей Google.
Директория по умолчанию для шрифтов ../fonts/
.
Современным браузерам достаточно файлов WOFF и WOFF2, а для устаревших нужны ещё форматы TTF, EOT и SVG. Например, один из вариантов — отказаться от «устаревших» форматов, отдавать только WOFF и WOFF2, а если у клиента старый браузер, то страница отобразится системным шрифтом, без загрузки лишних файлов.
В библиотеке Google Fonts шрифты оптимизируются, там ресурсы минимального размера. Так что для своего хостинга лучше брать файлы именно из этого источника.
Просто разместить файлы на своём сервере — недостаточно. Нужно обеспечить, чтобы шрифты загружались заранее, а не после парсинга CSS и создания CSSOM. Это делается через подсказку preload
.
Следует иметь в виду, что в таком случае браузер загрузит ресурсы в обязательном порядке независимо от того, понадобятся они ему впоследствии или нет.
Итак, единственным аргументом в пользу Google Fonts была быстрая и надёжная сеть доставки контента (CDN) с кэшированием. Google владеет точками присутствия у всех крупных провайдеров по всему миру.
Популярные шрифты вроде Open Sans и Roboto используются на многих сайтах. Идея была в том, что пользователю достаточно посетить один такой сайт — ресурсы загружаются один раз и хранятся в кэше браузера, так что при заходе на другой сайт они не будут скачиваться повторно.
Но теперь так больше не работает. Начиная с версии Chrome 86, которая вышла в октябре 2020 года, межсайтовые ресурсы вроде шрифтов больше не делят общий CDN из-за разделённого браузерного кэша (partitioned browser cache).
В блоге Google объясняется смысл этой функции, которая реализована для защиты от межсайтового трекинга. То есть для приватности. К сожалению, ради этого пришлось пожертвовать производительностью.
При запросе ресурсов с CDN раньше в качестве ключа кэша использовался соответствующий URL ресурса (того же шрифта). Таким образом, если два разных сайта запрашивали картинку или шрифт с одного и того же URL, то этот ресурс не скачивался дважды.
Долгое время такой механизм хорошо работал с точки зрения производительности. Однако в последнее время появились идеи, как его эксплуатировать во вред людям. Оказалось, что по отклику браузера можно определить, что браузер или 1) скачивает ли ресурс заново, или 2) ресурс уже есть в кэше. Соответственно, в достаточно продвинутой атаке можно понять, какие сайты этот браузер посещал в прошлом. А исследователи доказали, что по истории посещённых сайтов/страниц можно с высокой степенью достоверности идентифицировать личность пользователя, даже если браузер запущен в режиме инкогнито, блокируется JavaScript и удаляются куки. То есть история посещённых страниц — тоже подходящий вариант для фингерпринтинга.
Кроме фингерпринтинга, становится возможным межсайтовый трекинг, то есть отслеживание пользователей с уникальным ID на всех сайтах, которые участвуют в этой системе.
В такой ситуации Google ничего не оставалось, кроме как пожертвовать производительностью — и запретить в браузере совместное кэширование ресурсов, в том числе шрифтов.
В новой реализации в качестве ключа кэша используется не только URL ресурса, а новый составной параметр Network Isolation Key. Он состоит из трёх частей: домен верхнего уровня, домен текущего фрейма и URL ресурса.
Таким образом, при посещении нового сайта тот же шрифт будет скачиваться заново с того же URL.
Разделённый кэш присутствует в Safari c 2013 года. Остальные подтянулись только сейчас:
- Chrome: c версии 86 (октябрь 2020)
- Safari: с 2013 года
- Firefox: планируется реализовать
- Edge: вероятно, в ближайшее время
- Opera: вероятно, в ближайшее время
- Brave: вероятно, в ближайшее время
- Vivaldi: вероятно, в ближайшее время
Вслед за Chrome разделённый кэш планируют реализовать и разработчики Firefox, а затем с большой степенью вероятности и других браузеров, основанных на Chromium.
Таким образом, браузер всегда будет скачивать шрифты Google Fonts заново для каждого сайта. Последний аргумент в пользу использования общего кэша теперь не работает.
Печально, что из-за приватности приходится жертвовать производительностью и делать лишние сетевые запросы.
Что можно сделать пользователю, чтобы не скачивать шрифты каждый раз с каждого сайта?
- Отключить загрузку сторонних шрифтов в uBlock Origin.
- Отключить загрузку шрифтов в браузере.
- Firefox:
about:config
,gfx.downloadable_fonts.enabled
; - Chrome: запуск с параметром
--disable-remote-fonts
- Firefox:
- В качестве эксперимента попробовать локальный CDN, хотя Decentraleyes и LocalCDN на практике не кэшируют Google Fonts.
Раньше был вариант скачать все шрифты Google Fonts (около 300 МБ) и установить в системе. Но как сказано выше, такой вариант больше не работает из-за изменений @font-face
. Если сайт использует Google Fonts, шрифты всё равно будут загружаться каждый раз заново. Локальная установка не поможет.
На правах рекламы
Мощные серверы в аренду на базе новейших процессоров AMD EPYC для размещения веб-проектов любой сложности, от лендингов до крупных новостных порталов или интернет-магазинов. Создайте собственный тарифный план в пару кликов и приступите к работе уже через минуту!