Оптимизируем изображения, видео, шрифты и стили

Brotli для сжатия plain-text

В 2015 году Google представил опенсорсный формат сжатия без потерь Brotli. Сейчас этот формат поддерживается всеми современными браузерами. Энкодер для Brotli имеет 11 предустановленных степеней сжатия. При этом, чем сильнее сжатие, тем больше ресурсов понадобится для декодинга. Асет, пожатый Brotli с четвертым уровнем сжатия весит меньше, чем Gzip, сжимается быстрее и поддерживается большинством современных браузеров. Если вы уже используете gzip, переход на Brotli позволит улучшить размер асетов в несколько раз, и значительно снизит FCP. Если хотите, вы можете сравнить два этих алгоритма.
Brotli работает только через HTTPS. Он поддерживается CDN-провайдерами: Akamai, Netlify Edge, AWS, KeyCDN, Fastly, Cloudflare, CDN77. Brotli можно использовать без поддержки CDN (при помощи service worker).

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

Сравнение времени выполнения по степени сжатия. Неудивительно, что Brotli работает медленнее, чем gzip. (Увеличить изображение)
Ситуацию с трейдоффом можно немного улучшить. Формат Brotli содержит встроенный статический словарь. В этом словаре помимо различных строк на нескольких языках, можно использовать преобразования для этих слов, что значительно повышает гибкость. В своем исследовании Феликс Ханау нашёл способ улучшить сжатие при помощи этого трюка. Он использовал более специфический словарь для каждого типа данных. Тип данных он брал из «Content-Type» (HTML, CSS, JS). В результате Феликсу удалось добиться более высоких степеней сжатия, практически не снизив производительность (от 1% до 3%).
Продолжает эту идею исследование Елены Кириленко. Как утверждает Елена, «когда у нас уже есть ресурс, сжатый через Brotli, и мы пытаемся сжимать динамический контент, похожий на предыдущий, то можно добиться значительного улучшения времени сжатия».

По словам Елены, мы можем улучшить сжатие на 5,3% и увеличить его скорость на 39% при удалении 10% контента. При удалении 50% контента мы улучшаем сжатие ещё на 3,2% и на 26% увеличиваем его скорость.

Алгоритмы сжатия для Brotli постоянно улучшаются. Brotli определенно стоит использовать для сжатия статического контента. Это может быть любой plaintext — HTML, CSS, SVG, JavaScript, JSON и т. д.
Примечание: по состоянию на начало 2021 года примерно 60% HTTP-трафика вообще не сжимается, 30,82% сжимается с помощью Gzip и 9,1% сжимаются Brotli. Например, 23,4% страниц, использующих Angular, вообще не сжимаются.
Как правильно сжимать ваш контент? Сжимайте статику с помощью Brotli+Gzip, выбрав самый высокий уровень сжатия, а динамический контент сжимайте на лету Brotli, используя уровни 4−6. Убедитесь, что сервер правильно обрабатывает contant negotiation между Brotli и Gzip.

В 2020 году, 22,59% контента сжата Brotli. Примерно 77,39% сжато gzip. (Источник изображения: Web Almanac: Compression) (Увеличить)

Адаптивная загрузка мультимедиа и client hints

Еще раз напомним: используйте адаптивные изображения с «srcset», «sizes» и элементом <picture>. Это особенно важно для приложений, с тяжёлыми мультимедийными данными. Адаптивная загрузка медиа (в этом примере — React+Next.js) позволяет учитывать пропускную способность сети и объём памяти на разных устройствах. В контексте React добиться этого можно с помощью client hints на сервере и react-adaptive-hooks на клиенте.
Client hints добавляют в HTTP-запрос дополнительные заголовки: DPR, Viewport-Width, Width, Save-Data, Accept, указывающих на предпочтительный формат изображения. Задача этих заголовков — информировать сервер об особенностях браузера пользователя, экрана, подключения и т. д.

Сервер получает от браузера информацию, какой тип контента тот предпочитает получить и решает, как заполнить макет. Таким образом, с помощью client hints, мы убираем выбор размеров изображений из разметки HTML и отдаём его серверу.

Адаптивная загрузка мультимедиа. Текст отправляется пользователям, которые не в сети, изображение с низким разрешением — пользователям 2G, изображение с высоким разрешением — пользователям 3G и HD-видео для пользователей 4G. Источник: Loading web pages fast on a $ 20 feature phone. (Увеличить)
Однако, как заметил Илья Григорик, client hints — это дополнительный инструмент, но никак не альтернатива адаптивным изображениям. «Элемент <picture> в HTML-разметке даёт необходимый контроль над art-direction. Client hints описывают результирующее изображение и позволяют автоматизировать выбор ресурса. Service Worker обеспечивает управление запросами и ответами на стороне клиента».

Так например, service worker, может добавлять к запросу новые значения заголовков, перезаписывать URL-адрес и направлять запрос изображения на CDN, адаптировать ответ в зависимости от качества подключения и предпочтений пользователя и т. д. Это относится не только к изображениям, но и ко всем остальным запросам.

Для клиентов, поддерживающих client hints, экономия в весе изображений может достигать 42%. Сделав замеры для Smashing Magazine, мы заметили улучшение на 19−32%.

Вы используете адаптивные изображения для фона?

С помощью CSS image-set, который поддерживается в Safari 14 и в большинстве современных браузеров (кроме Firefox) можно обеспечить адаптивность фоновых изображений:
В принципе, таким образом можно обслуживать фоновые изображения низкого разрешения с 1x-дескриптором, изображения более высокого разрешения с 2x-дескриптором и даже изображения печатного качества с разрешением 600 dpi.

А как насчёт WebP?

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

Не будет лишним изучить возможности формата WebP. WebP можно использовать практически в любом браузере с элементом <picture> и резервным JPEG при необходимости (см. фрагмент кода Андреаса Бовенса) или через согласование содержимого (с помощью заголовков Accept).

Но у формата WebP есть свои недостатки. Размеры изображений WebP более компактны по сравнению с Guetzli и Zopfli. Но WebP, в отличие от JPEG, не поддерживает прогрессивный рендеринг. Да, WebP быстрее доставляются по сети, но изображение хорошего качества пользователь, скорее всего, увидит со старым добрым JPEG. JPEG может обеспечить вполне приличную картинку с половиной или даже четвертью переданных данных (остальное загрузится позже). В то время как с WebP при задержке передачи данных пользователь увидит полупустую страницу.

Что же выбрать? Смотря, что вам нужно. С WebP вы уменьшите полезную нагрузку, а с JPEG улучшите воспринимаемую пользователем производительность. Хотите узнать больше о WebP? Посмотрите видео WebP Rewind talk от Паскаля Массимино (Pascal Massimino) из Google.

Для преобразования в формат WebP можно использовать WebP Converter, cwebp или libwebp. Подробный тьюториал — здесь. Также Виталий Фридман советует прочесть статью Джоша Комо о внедрении современных форматов изображений. Что касается графических редакторов, то Sketch поддерживает WebP, а из Photoshop вы можете экспортировать изображения в WebP с помощью плагина WebP. Есть и другие способы. Существуют расширения для WordPress (Optimus, Cache Enabler) и Joomla есть расширения, реализующие поддержку WebP. При использовании React, стилизованных компонентов или gatsby-изображения можно не заморачиваться с элементом <picture>.

Джереми Вагнер опубликовал целую книгу о WebP на smashingmagazine.com.

Давайте поговорим про AVIF

AVIF — формат изображения, основанный на видеокодеке AV1. Формат поддерживает сжатие с потерями и без потерь, анимацию, альфа-канал с потерями. Кроме того, AVIF лучше, чем JPEG обрабатывает четкие линии и сплошные цвета.

По сравнению с WebP и JPEG, AVIF работает значительно лучше, уменьшая размер файла до 50% при том же DSSIM. В своем посте об оптимизации загрузки изображений Мальте Убл (Malte Ubl) отмечает, что AVIF «превосходит JPEG по многим параметрам. И при этом выгодно отличается от WebP, который зачастую оптимизирует изображения хуже, чем JPEG и может терять данные из-за отсутствия прогрессивного рендеринга».