Производительность изображения

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

Изображения можно добавлять на страницу с помощью элементов <img> или <picture> или свойства CSS background-image .

Размер изображения

Первая оптимизация, которую вы можете выполнить, когда дело доходит до использования ресурсов изображения, — это отобразить изображение правильного размера — в данном случае термин «размер» относится к размерам изображения. Если не учитывать никаких других переменных, изображение, отображаемое в контейнере размером 500 на 500 пикселей, будет иметь оптимальный размер 500 на 500 пикселей. Например, использование квадратного изображения размером 1000 пикселей означает, что изображение в два раза больше необходимого.

Однако при выборе правильного размера изображения участвует множество переменных, что делает задачу выбора правильного размера изображения в каждом случае довольно сложной. В 2010 году, когда был выпущен iPhone 4, разрешение экрана (640x960) было вдвое больше, чем у iPhone 3 (320x480). Однако физический размер экрана iPhone 4 остался примерно таким же, как у iPhone 3.

Отображение всего с более высоким разрешением сделало бы текст и изображения значительно меньше — точнее, вдвое меньше их предыдущего размера. Вместо этого 1 пиксель стал 2 пикселями устройства . Это называется соотношением пикселей устройства (DPR) . У iPhone 4 и многих моделей iPhone, выпущенных после него, DPR составлял 2.

Возвращаясь к предыдущему примеру, если устройство имеет DPR, равный 2, и изображение отображается в контейнере размером 500 на 500 пикселей, то квадратное изображение размером 1000 пикселей (называемое внутренним размером ) теперь является оптимальным размером. Аналогично, если устройство имеет DPR, равный 3, то оптимальным размером будет квадратное изображение размером 1500 пикселей.

srcset

Элемент <img> поддерживает атрибут srcset , который позволяет указать список возможных источников изображений, которые может использовать браузер. Каждый указанный источник изображения должен включать URL-адрес изображения и дескриптор ширины или плотности пикселей.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

Предыдущий фрагмент HTML использует дескриптор плотности пикселей, чтобы намекнуть браузеру использовать image-500.png на устройствах с DPR, равным 1, image-1000.jpg на устройствах с DPR, равным 2, и image-1500.jpg на устройствах с ДНР 3.

Хотя все это может показаться банальным, DPR экрана — не единственный фактор при выборе оптимального изображения для данной страницы. Макет страницы является еще одним фактором.

sizes

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

Атрибут sizes позволяет указать набор исходных размеров, где каждый исходный размер состоит из условия носителя и значения. Атрибут sizes описывает предполагаемый размер отображения изображения в пикселях CSS. В сочетании с дескрипторами ширины srcset браузер может выбрать, какой источник изображения лучше всего подходит для устройства пользователя.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

В предыдущем фрагменте HTML атрибут srcset указывает список кандидатов на изображение, из которых браузер может выбрать, разделенный запятыми. Каждый кандидат в списке состоит из URL-адреса изображения, за которым следует синтаксис, обозначающий внутреннюю ширину изображения. Внутренний размер изображения — это его размеры. Например, дескриптор 1000w означает, что внутренняя ширина изображения составляет 1000 пикселей.

Используя эту информацию, браузер оценивает состояние мультимедиа в атрибуте sizes и — в данном случае — получает указание, что если ширина области просмотра устройства превышает 768 пикселей, изображение отображается с шириной 500 пикселей. На устройствах меньшего размера изображение отображается с 100vw или на всю ширину области просмотра.

Затем браузер может объединить эту информацию со списком источников изображений srcset , чтобы найти оптимальное изображение. Например, если пользователь находится на мобильном устройстве с шириной экрана 320 пикселей и DPR, равным 3, изображение отображается с разрешением 320 CSS pixels x 3 DPR = 960 device pixels . В этом примере изображением ближайшего размера будет image-1000.jpg , внутренняя ширина которого равна 1000 пикселей ( 1000w ).

Форматы файлов

Браузеры поддерживают несколько различных форматов файлов изображений. Современные форматы изображений, такие как WebP и AVIF, могут обеспечивать лучшее сжатие, чем PNG или JPEG, что уменьшает размер файла изображения и, следовательно, занимает меньше времени на загрузку. Предоставляя изображения в современных форматах, вы можете сократить время загрузки ресурса , что может привести к снижению значения Largest Contentful Paint (LCP) .

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

AVIF — это новый формат изображений, и хотя он не так широко поддерживается, как WebP, он пользуется достаточно приличной поддержкой во всех браузерах . AVIF поддерживает сжатие как с потерями, так и без потерь, и тесты показали в некоторых случаях экономию более 50% по сравнению с JPEG. AVIF также предлагает функции широкой цветовой гаммы (WCG) и расширенного динамического диапазона (HDR) .

Сжатие

Что касается изображений, существует два типа сжатия:

  1. Сжатие с потерями
  2. Сжатие без потерь

Сжатие с потерями снижает точность изображения за счет квантования , а дополнительная информация о цвете может быть отброшена с помощью субдискретизации цветности . Сжатие с потерями наиболее эффективно для изображений высокой плотности с большим количеством шума и цветов — обычно это фотографии или изображения с похожим содержанием. Это связано с тем, что артефакты , возникающие при сжатии с потерями, гораздо реже заметны на таких детальных изображениях. Однако сжатие с потерями может быть менее эффективным для изображений, содержащих острые края, таких как штриховые рисунки, столь же резкие детали или текст. Сжатие с потерями можно применять к изображениям JPEG, WebP и AVIF.

Сжатие без потерь уменьшает размер файла за счет сжатия изображения без потери данных. Сжатие без потерь описывает пиксель на основе отличия от соседних пикселей. Сжатие без потерь используется для форматов изображений GIF, PNG, WebP и AVIF.

Вы можете сжимать изображения с помощью Squoosh , ImageOptim или службы оптимизации изображений. При сжатии не существует универсальной настройки, подходящей для всех случаев. Рекомендуемый подход — экспериментировать с различными уровнями сжатия, пока не найдете хороший компромисс между качеством изображения и размером файла. Некоторые расширенные службы оптимизации изображений могут сделать это автоматически, но могут оказаться финансово невыгодными для всех пользователей.

Элемент <picture>

Элемент <picture> обеспечивает большую гибкость при указании нескольких кандидатов-изображений:

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

Когда вы используете элементы <source> в элементе <picture> , вы можете добавить поддержку изображений AVIF и WebP, но вернуться к более совместимым устаревшим форматам изображений, если браузер не поддерживает современные форматы. При таком подходе браузер выбирает первый указанный элемент <source> , который соответствует. Если он может визуализировать изображение в этом формате, он использует это изображение. В противном случае браузер переходит к следующему указанному элементу <source> . В предыдущем фрагменте HTML формат AVIF имеет приоритет над форматом WebP и возвращается к формату JPEG, если ни AVIF, ни WebP не поддерживаются.

Для элемента <picture> требуется вложенный в него элемент <img> . Атрибуты alt , width и height определены в <img> и используются независимо от того, какой <source> выбран.

Элемент <source> также поддерживает атрибуты media , srcset и sizes . Как и в предыдущем примере <img> , они указывают браузеру, какое изображение выбрать в разных окнах просмотра.

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

Атрибут media принимает медиа-условие . В предыдущем примере DPR устройства используется в качестве условия носителя. Любое устройство с DPR, превышающим или равным 1,5, будет использовать первый элемент <source> . Элемент <source> сообщает браузеру, что на устройствах с окном просмотра шириной более 768 пикселей выбранное изображение-кандидат отображается с шириной 500 пикселей. На небольших устройствах это занимает всю ширину области просмотра. Комбинируя атрибуты media и srcset , вы можете более точно контролировать, какое изображение использовать.

Это показано в следующей таблице, где оцениваются несколько значений ширины области просмотра и соотношения пикселей устройства:

Ширина области просмотра (пикселей) 1 ДНР 1,5 ДНР 2 ДНР 3 ДНР
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 год 500.jpg 1000.jpg 1000.jpg 1500.jpg

Устройства с DPR, равным 1, загружают изображение image-500.jpg , включая большинство пользователей настольных компьютеров, которые просматривают изображение с внешним размером 500 пикселей в ширину. С другой стороны, мобильные пользователи с DPR 3 загружают потенциально более крупный image-1500.jpg — то же изображение, которое используется на настольных устройствах с DPR 3.

<picture>
  <source
    media="(min-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

В этом примере элемент <picture> настроен для включения дополнительного элемента <source> для использования разных изображений для широких устройств с высоким DPR:

Ширина области просмотра (пикселей) 1 ДНР 1,5 ДНР 2 ДНР 3 ДНР
320 500.jpg 500.jpg 500.jpg 1000-см.jpg
480 500.jpg 500.jpg 1000-см.jpg 1500-см.jpg
560 500.jpg 1000-см.jpg 1000-см.jpg 1500-см.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 год 500.jpg 1000.jpg 1000.jpg 1500.jpg

С помощью этого дополнительного запроса вы можете увидеть, что image-1000-sm.jpg и image-1500-sm.jpg отображаются в небольших окнах просмотра. Эта дополнительная информация позволяет дополнительно сжимать изображения, поскольку артефакты сжатия не так заметны при таком размере и плотности, а также не ухудшают качество изображения на настольных устройствах.

В качестве альтернативы, настроив атрибуты srcset и media , вы можете избежать показа больших изображений на маленьких окнах просмотра:

<picture>
  <source
    media="(min-width: 560px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

В предыдущем фрагменте HTML дескрипторы ширины были удалены в пользу дескрипторов соотношения пикселей устройства. Изображения, отображаемые на мобильном устройстве, ограничены /image-500.jpg или /image-1000.jpg даже на устройствах с DPR 3.

Как управлять сложностью

Работая с адаптивными изображениями, вы можете столкнуться с множеством различных размеров и форматов для каждого изображения. В предыдущем примере используются варианты для каждого размера, но исключаются AVIF и WebP. Сколько вариантов должно быть? Как и во многих инженерных проблемах, ответ обычно звучит так: «Это зависит от обстоятельств».

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

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

Помимо этого, размер вашего HTML-документа увеличивается с каждым изменением. Вы можете отправить несколько килобайт HTML для каждого изображения.

Подавать изображения на основе заголовка запроса Accept .

Заголовок HTTP-запроса Accept сообщает серверу, какие типы контента понимает браузер пользователя. Эта информация может использоваться вашим сервером для предоставления оптимального формата изображения без добавления дополнительных байтов в ваши HTML-ответы.

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

Приведенный выше фрагмент HTML представляет собой упрощенную версию кода, которую вы можете добавить в серверную часть JavaScript вашего сервера, чтобы выбрать и использовать оптимальный формат изображения. Если заголовок Accept запроса включает image/avif , то обслуживается изображение AVIF. В противном случае, если заголовок Accept содержит image/webp , будет отправлено изображение WebP. Если ни одно из этих условий не соответствует действительности, то обслуживается изображение JPEG.

Вы можете изменять ответы на основе содержимого заголовка запроса Accept практически на каждом типе веб-сервера — например, вы можете переписать запросы изображений на серверах Apache на основе заголовка Accept , используя mod_rewrite .

Это мало чем отличается от поведения, которое можно найти в сети доставки контента изображений (CDN) . CDN изображений — отличные решения для оптимизации изображений и отправки оптимального формата в зависимости от устройства и браузера пользователя.

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

Ленивая загрузка

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

decoding

Атрибут decoding сообщает браузеру, как ему следует декодировать изображение. Значение async сообщает браузеру, что изображение может быть декодировано асинхронно, что, возможно, сокращает время рендеринга другого контента. Значение sync сообщает браузеру, что изображение должно отображаться одновременно с другим контентом. Значение по умолчанию auto позволяет браузеру решать, что лучше для пользователя.

Демонстрационные изображения

Проверьте свои знания

Какие форматы изображений поддерживают сжатие без потерь ?

Гиф.
Правильный!
JPEG.
Попробуйте еще раз.
PNG.
Правильный!
ВебП.
Правильный!
АВИФ.
Правильный!

Какие форматы изображений поддерживают сжатие с потерями ?

Гиф.
Попробуйте еще раз. Хотя формат GIF поддерживает только ограниченную палитру из 256 цветов, перед преобразованием в GIF необходимо выполнить кодирование с потерями.
JPEG.
Правильный!
PNG.
Попробуйте еще раз.
ВебП.
Правильный!
АВИФ.
Правильный!

Что дескриптор ширины (например, 1000w ) сообщает браузеру о кандидате изображения, указанном в атрибуте srcset ?

Внешняя ширина изображения, то есть размеры изображения в макете после применения стилей к странице.
Попробуйте еще раз.
Внутренняя ширина изображения, то есть размеры самого изображения.
Правильный!

Что атрибут sizes сообщает браузеру об элементе <img> , к которому он применен?

Логика, которая определяет, какой кандидат, указанный в srcset элемента <img> , должен быть загружен, учитывая размеры текущего окна просмотра пользователя.
Правильный!
Внутренняя ширина изображения, загружаемого из атрибута srcset элемента <img> .
Попробуйте еще раз.

Далее: Видео-спектакль

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