- PVSM.RU - https://www.pvsm.ru -
Шрифты Google Fonts страшно популярны. Их загружают более 42,8 миллиона сайтов [1], в том числе Хабр [2]. Библиотека Google Fonts содержит 1023 свободных шрифта и программные интерфейсы для их внедрения через CSS. Очень удобно, казалось бы.
Во многих [3] статьях [4] отмечалось [5], в какую цену [6] обходятся многочисленные запросы через API. Совет самостоятельно хостить шрифты дают много лет. Даже сама Google давала такой совет на конференции Google I/O 2018 года в выступлении на тему веб-производительности [7].
Так почему же многие до сих пор загружают шрифты через Google Fonts API? Ну, был последний аргумент — кэширование. Мол, благодаря общему CDN пользователю не нужно скачивать шрифт заново с каждого сайта. Однако в октябре 2020 года этот аргумент перестал работать. Теперь шрифты Google Fonts больше не кэшируются!
По своей природе Google Fonts даже со всеми оптимизациями не может загружаться клиенту быстрее, чем с родного
Загрузка Google Fonts без preconnect
Оптимизированная загрузка Google Fonts с опцией preconnect (подсказка для браузера заранее подключиться к домену fonts.gstatic.com, чтобы ускорить установку соединения в будущем):
Загрузка Google Fonts с preconnect
Дело в том, что Google всегда запрашивает с сервера таблицу стилей:
<link href="https://fonts.googleapis.com/css?family=Muli:400" rel="stylesheet">
Она загружается в любом случае. А уже потом декларация @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
Загрузка со своего
Как видим, во втором случае запросы к fonts.gstatic.com отсутствуют, что сразу сокращает время загрузки страницы. Это самый оптимальный вариант.
Марио Ранфтль [10] создал очень полезный справочник google-webfonts-helper [11]. Здесь можно выбрать конкретные шрифты из библиотеки Google Fonts, нужные наборы символов, начертания, посмотреть поддержку в браузерах — и получить код CSS и непосредственно сами файлы. То есть можно перенести нужные шрифты на свой
Выбираем шрифт, наборы символов и стили. Чем больше стилей мы выберем, тем больше объём скачивания для клиента.
У разных семейств шрифтов разные уровни проработки. Например, кириллицу поддерживают только 118 из 1023 шрифтов [12] на Google Fonts. Не все шрифты поддерживают полный набор начертаний.
[13]
Самое популярное в коллекции 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
.
<link rel="preload" as="font" type="font/woff2"
href="./fonts/muli-v12-latin-regular.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2"
href="./fonts/muli-v12-latin-700.woff2" crossorigin>
Следует иметь в виду, что в таком случае браузер загрузит ресурсы в обязательном порядке независимо от того, понадобятся они ему впоследствии или нет.
Итак, единственным аргументом в пользу Google Fonts была быстрая и надёжная сеть доставки контента (CDN) с кэшированием. Google владеет точками присутствия у всех крупных провайдеров по всему миру.
Популярные шрифты вроде Open Sans и Roboto используются на многих сайтах. Идея была в том, что пользователю достаточно посетить один такой сайт — ресурсы загружаются один раз и хранятся в кэше браузера, так что при заходе на другой сайт они не будут скачиваться повторно.
Но теперь так больше не работает. Начиная с версии Chrome 86, которая вышла в октябре 2020 года, межсайтовые ресурсы вроде шрифтов больше не делят общий CDN из-за разделённого браузерного кэша (partitioned browser cache).
В блоге Google [14] объясняется смысл этой функции, которая реализована для защиты от межсайтового трекинга. То есть для приватности. К сожалению, ради этого пришлось пожертвовать производительностью.
При запросе ресурсов с CDN раньше в качестве ключа кэша использовался соответствующий URL ресурса (того же шрифта). Таким образом, если два разных сайта запрашивали картинку или шрифт с одного и того же URL, то этот ресурс не скачивался дважды.
Долгое время такой механизм хорошо работал с точки зрения производительности. Однако в последнее время появились идеи, как его эксплуатировать во вред людям. Оказалось, что по отклику браузера можно определить, что браузер или 1) скачивает ли ресурс заново, или 2) ресурс уже есть в кэше. Соответственно, в достаточно продвинутой атаке [15] можно понять, какие сайты этот браузер посещал в прошлом. А исследователи доказали, что по истории посещённых сайтов/страниц можно с высокой степенью достоверности идентифицировать личность пользователя, даже если браузер запущен в режиме инкогнито, блокируется JavaScript и удаляются куки. То есть история посещённых страниц — тоже подходящий вариант для фингерпринтинга.
Кроме фингерпринтинга, становится возможным межсайтовый трекинг, то есть отслеживание пользователей с уникальным ID на всех сайтах, которые участвуют в этой системе.
В такой ситуации Google ничего не оставалось, кроме как пожертвовать производительностью — и запретить в браузере совместное кэширование ресурсов, в том числе шрифтов.
В новой реализации в качестве ключа кэша используется не только URL ресурса, а новый составной параметр Network Isolation Key. Он состоит из трёх частей: домен верхнего уровня, домен текущего фрейма и URL ресурса.
Таким образом, при посещении нового сайта тот же шрифт будет скачиваться заново с того же URL.
Разделённый кэш присутствует в Safari c 2013 года. Остальные подтянулись только сейчас:
- Chrome: c версии 86 (октябрь 2020)
- Safari: с 2013 года
- Firefox: планируется реализовать [16]
- Edge: вероятно, в ближайшее время
- Opera: вероятно, в ближайшее время
- Brave: вероятно, в ближайшее время
- Vivaldi: вероятно, в ближайшее время
Вслед за Chrome разделённый кэш планируют реализовать и разработчики Firefox, а затем с большой степенью вероятности и других браузеров, основанных на Chromium.
Таким образом, браузер всегда будет скачивать шрифты Google Fonts заново для каждого сайта. Последний аргумент в пользу использования общего кэша теперь не работает.
Печально, что из-за приватности приходится жертвовать производительностью и делать лишние сетевые запросы.
Что можно сделать пользователю, чтобы не скачивать шрифты каждый раз с каждого сайта?
about:config
, gfx.downloadable_fonts.enabled
;
--disable-remote-fonts
Раньше был вариант скачать все шрифты Google Fonts (около 300 МБ) и установить в системе. Но как сказано выше, такой вариант больше не работает из-за изменений @font-face
. Если сайт использует Google Fonts, шрифты всё равно будут загружаться каждый раз заново. Локальная установка не поможет.
Мощные серверы [21] в аренду на базе новейших процессоров AMD EPYC для размещения веб-проектов любой сложности, от лендингов до крупных новостных порталов или интернет-магазинов. Создайте собственный тарифный план в пару кликов и приступите к работе уже через минуту!
Автор: Mikhail
Источник [22]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/chrome/359802
Ссылки в тексте:
[1] 42,8 миллиона сайтов: https://trends.builtwith.com/websitelist/Google-Font-API
[2] Хабр: https://builtwith.com/habr.com
[3] многих: https://blog.cloudflare.com/fast-google-fonts-with-cloudflare-workers/
[4] статьях: https://medium.com/clio-calliope/making-google-fonts-faster-aadf3c02a36d
[5] отмечалось: https://www.keycdn.com/blog/web-font-performance#disadvantages-of-web-fonts
[6] в какую цену: https://blog.logrocket.com/self-hosted-fonts-vs-google-fonts-api/
[7] выступлении на тему веб-производительности: https://www.youtube.com/watch?v=Mv-l3-tJgGk&feature=youtu.be&t=24m58s
[8] хостинга: https://www.reg.ru/?rlink=reflink-717
[9] здесь: https://habr.com/ru/company/vdsina/blog/490366/
[10] Марио Ранфтль: http://mranftl.com/
[11] google-webfonts-helper: https://google-webfonts-helper.herokuapp.com/fonts
[12] 118 из 1023 шрифтов: https://fonts.google.com/?subset=cyrillic
[13] Image: https://habrastorage.org/webt/wk/sc/w1/wkscw15wtrgultwhyzlmlrf_msm.png
[14] блоге Google: https://wicki.io/posts/2020-11-goodbye-google-fonts/
[15] достаточно продвинутой атаке: http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html
[16] планируется реализовать: https://bugzilla.mozilla.org/show_bug.cgi?id=1590107
[17] Decentraleyes: https://addons.mozilla.org/en-US/firefox/addon/decentraleyes/
[18] LocalCDN: https://codeberg.org/nobody/LocalCDN/src/branch/main/resources
[19] не: https://codeberg.org/nobody/LocalCDN/issues/159
[20] кэшируют: https://github.com/Synzvato/decentraleyes/issues/34
[21] Мощные серверы: https://vdsina.ru/cloud-servers?partner=habr204
[22] Источник: https://habr.com/ru/post/533208/?utm_source=habrahabr&utm_medium=rss&utm_campaign=533208
Нажмите здесь для печати.