Google Fonts и font-display: особенности взаимодействия

Google Fonts и font-display: особенности взаимодействия

От автора: дескриптор font-display блоков @font-face действительно хорош. Само по себе это имеет большое значение для улучшения воспринимаемой производительности загрузки веб-шрифтов. Загрузка веб-шрифтов — сложная задача, и наличие инструмента, который работает так хорошо, как он, имеет большое значение для Интернета.

Это настолько большое дело, что Pagespeed Insights / Lighthouse от Google предупредят вас, если вы не используете его. Горькая ирония заключается в том, что их в собственных Google Fonts font display никак не используется, а ведь это наиболее часто используемый репозиторий пользовательских шрифтов в Интернете.

Даниэль Дудас так описал ситуацию: Разработчики Google предлагают использовать Lighthouse -> Lighthouse предупреждает о неиспользовании при загрузке шрифтов font-display -> Веб-страница использует шрифты Google так, как это предлагается в Google Fonts -> Google Fonts не поддерживает font-display -> Облом.

По сути, мы, разработчики, хотели бы получить font-display в блоке @font-face, который обслуживает Google, например:

@font-face { font-family: "Open Sans Regular"; src: url("..."); font-display: swap;
}

Или какую-то альтернативу, которая так же проста и эффективна.

Похоже, параметры запроса это возможность

Когда вы используете Google Font, они дают вам URL, который обрабатывает таблицу стилей и заставляет шрифт работать. Например:

https://fonts.googleapis.com/css?family=Roboto

Они также поддерживают параметры URL для различных вещей, например, для толщины:

https://fonts.googleapis.com/css?family=Open+Sans:400,700

и подмножеств:

http://fonts.googleapis.com/css?family=Creepster&text=TRICKS
https://fonts.googleapis.com/css?family=Open+Sans:400,700&subset=cyrillic

Так почему не сделать это…

http://fonts.googleapis.com/css?family=Creepster&font-display=swap

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

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

Они снова говорят об этом, поэтому кажется маловероятным, что в ближайшее время мы получим параметры запроса, но я бы хотел ошибиться.

Вариант: скачать и самостоятельно разместить их

Все шрифты Google имеют открытый исходный код, поэтому мы можем получить их копию, чтобы использовать все, что захотим.

Google Fonts и font-display: особенности взаимодействия

Когда файлы шрифтов размещаются и обслуживаются нами самостоятельно, мы, по сути, пишем блоки @font-face, и мы можем включать любые font-display, какие захотим.

Вариант: извлекать и изменять

Робин Рихтсфельд предложил идею запускать для шрифта Ajax-вызов из JavaScript, а затем изменять ответ, чтобы добавить font-display и включить его.

const loadFont = (url) => { // the 'fetch' equivalent has caching issues var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { let css = xhr.responseText; css = css.replace(/}/g, 'font-display: swap; }'); const head = document.getElementsByTagName('head')[0]; const style = document.createElement('style'); style.appendChild(document.createTextNode(css)); head.appendChild(style); } }; xhr.send();
} loadFont('https://fonts.googleapis.com/css?family=Rammetto+One');

Умно! Хотя я не совсем уверен, как это вписывается в то, как сейчас происходит загрузка шрифтов. Поскольку мы обрабатываем загрузку этого шрифта в JavaScript, производительность загрузки зависит от того, когда и как мы загружаем скрипт, который это выполняет. Если мы собираемся сделать это, возможно, нам следует изучить использование официального веб-шрифта?

Вариант: Service Workers

Как и в предыдущем методе, мы можем извлечь шрифт и изменить его, но сделать это на уровне Service Worker, чтобы иметь возможность его кэшировать (возможно, более эффективно). Адам Лейн предложил это:

self.addEventListener("fetch", event => { event.respondWith(handleRequest(event))
}); async function handleRequest(event) { const response = await fetch(event.request); if (event.request.url.indexOf("https://fonts.googleapis.com/css") === 0 && response.status < 400) { // Исходя из того, что у вас настроено специфичное имя кэша const cache = await caches.open("google-fonts-stylesheets"); const cacheResponse = await cache.match(event.request); if (cacheResponse) { return cacheResponse; } const css = await response.text(); const patched = css.replace(/}/g, "font-display: swap; }"); const newResponse = new Response(patched, {headers: response.headers}); cache.put(event.request, newResponse.clone()); return newResponse; } return response;
}

Даже Google согласен, что использование Service Workers для помощи Google Fonts — хорошая идея. Workbox, их библиотека для абстрагирования управления Service Workers, использует Google Fonts в качестве демонстрации на главной странице:

// Кэшируем таблицу стилей Google Fonts в соответствии со стратегией устаревания во время ревалидации.
workbox.routing.registerRoute( /^https:\/\/fonts\.googleapis\.com/, workbox.strategies.staleWhileRevalidate({ cacheName: 'google-fonts-stylesheets', }),
); // Кэшируем файлы веб-шрифтов Google Fonts в соответствии с первой стратегией кэширования на 1 год.
workbox.routing.registerRoute( /^https:\/\/fonts\.gstatic\.com/, workbox.strategies.cacheFirst({ cacheName: 'google-fonts-webfonts', plugins: [ new workbox.cacheableResponse.Plugin({ statuses: [0, 200], }), new workbox.expiration.Plugin({ maxAgeSeconds: 60 * 60 * 24 * 365, }), ], }),
);

Вариант: Cloudflare Workers

Пьер-Люк Жендро решил использовать Cloudflare workers для решения этой проблемы, но затем разработал Supercharge Google Fonts с помощью Cloudflare и Service Workers, очевидно, для еще лучшей производительности. Это его репо.

Вариант: ждать @font-feature-values

Одна из причин, по которой, возможно, Google не торопится (и они говорят то же самое) — есть новое @rule CSS, называемое @font-feature-values, которое предназначено именно для этой ситуации. Вот спецификация:

Этот механизм может использоваться для установки политики отображения по умолчанию для всего семейства шрифтов и позволяет разработчикам устанавливать политику отображения для правил @ font-face, которые не находятся под их непосредственным контролем. Например, когда шрифт обслуживается сторонним поставщиком шрифтов, разработчик не контролирует правила @font-face, но все же может установить политику отображения шрифтов по умолчанию для предоставленного семейства шрифтов. Возможность установить политику по умолчанию для всего семейства шрифтов также полезна, чтобы избежать несоответствия формы шрифта, потому что политика отображения затем применяется ко всему семейству шрифтов.

Похоже, это не слишком будет отличаться от остальных методов (лишь немного), но ждать это не так уж и круто.

Автор: Chris Coyier

Источник: https://css-tricks.com/

Редакция: Команда webformyself.