Основные проблемы производительности

В настоящее время изображения являются самыми крупными объектами в интернете как с точки зрения общего размера передачи, так и с точки зрения количества запросов на страницу. По состоянию на июнь 2022 года медианный размер веб-страницы составляет около 2 МБ, и почти половина этого объема приходится на изображения. Без преувеличения можно сказать, что оптимизация запросов изображений может быть самой большой оптимизацией производительности, которую вы можете сделать.

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

Отложенные запросы изображений

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

<img src="image.jpg" loading=&quo>t;lazy" alt="…"

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

Несмотря на простоту, использование этого атрибута может оказать огромное положительное влияние на производительность: изображение, которое никогда не попадает в область просмотра пользователя, никогда не будет запрошено, и пропускная способность не будет тратиться на изображения, которые пользователь никогда не увидит.

Однако у этого подхода есть недостаток: откладывая запросы, вы не используете преимущества оптимизированных процессов браузера, которые позволяют запрашивать изображения как можно раньше. Если атрибут loading="lazy" используется для элементов img в верхней части макета, которые с большей вероятностью будут находиться в области просмотра пользователя при первой загрузке страницы, то загрузка этих изображений может показаться конечному пользователю значительно более медленной.

Приоритет загрузки

Атрибут loading – это пример того, как веб-стандарты помогают разработчикам управлять приоритетом запросов в браузерах.

Вы, вероятно, знаете о базовых подходах браузеров к приоритету загрузки. Например, запрос внешнего CSS-файла в элементе <head> документа считается достаточно важным, чтобы заблокировать отрисовку, а запрос внешнего файла JavaScript непосредственно над элементом </body> будет отложен до завершения отрисовки. Если атрибут loading элемента <img> имеет значение lazy, запрос связанного изображения будет отложен до тех пор, пока браузер не определит, что оно будет показано пользователю. В противном случае приоритет этого изображения будет таким же, как и у других изображений на странице.

Атрибут fetchpriority предназначен для того, чтобы дать разработчикам более точный контроль над приоритетом объектов, позволяя помечать ресурсы как имеющие высокий и низкий приоритет по сравнению с ресурсами того же типа. Атрибут fetchpriority используется в тех же случаях, что и loading, но его область применения гораздо шире. Например, вы можете использовать fetchpriority="low" для изображения, которое появляется только после взаимодействия с пользователем (независимо от того, попадает ли оно в область просмотра), чтобы отдать приоритет видимым изображениям в других местах страницы, или fetchpriority="high", чтобы отдать приоритет изображению, которое сразу же появится в области просмотра после отрисовки страницы.

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

Как оценить эффективность изображений

При оптимизации объектов изображений воспринимаемая производительность часто важнее и ее сложнее измерить, чем общий размер передачи.

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

совокупное смещение макета

Совокупное смещение макета (CLS) – это показатель визуальной стабильности. Этот показатель позволяет определить, насколько сильно меняется макет контента на странице по мере загрузки объектов и отрисовки страницы. Любой, кто провел значительное количество времени в Интернете, терял свое место в длинном тексте из-за «прыжка» страницы, когда внезапно отображался задержанный веб-шрифт или источник изображения, или интерактивный элемент внезапно перемещался от указателя. Высокое значение CLS в лучшем случае раздражает, а в худшем – приводит к ошибкам. Например, пользователь может нажать кнопку "Отмена", которая сместилась на место кнопки "Подтвердить".

Учитывая время загрузки и объём пространства, которое они могут занимать в макете, разумно предположить, что изображения являются частой причиной высоких показателей CLS.

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

Если вы уже несколько лет занимаетесь фронтенд-разработкой, то наверняка знакомы с атрибутами width и height тега <img>. До широкого распространения CSS это был единственный способ задать размер изображения.

<img src="image.jpg" height="200"> width="400" alt="…"

Эти атрибуты перестали использоваться, чтобы отделить стили от разметки, особенно когда адаптивный дизайн потребовал указывать размеры в процентах с помощью CSS. На ранних этапах развития адаптивного веб-дизайна часто рекомендовалось удалять неиспользуемые атрибуты width и height, поскольку значения, указанные в CSS (max-width: 100% и height: auto), переопределяли их.

<img src="image.jpg&quo>t; alt="…"
img {
  max-width: 100%;
  height: auto;
}

Если удалить атрибуты height и width, как в предыдущем примере, то браузер сможет определить высоту изображения только одним способом: запросить источник, проанализировать его и отобразить с исходным соотношением сторон, исходя из ширины пространства, которое изображение занимает в макете после применения таблиц стилей. Большая часть этого процесса происходит после рендеринга страницы, при этом вновь рассчитанная высота вызывает дополнительные сдвиги макета.

С 2019 года браузеры обрабатывают атрибуты width и height по-новому. Вместо того чтобы использовать значения этих атрибутов для определения фиксированного размера элемента img в макете, можно считать, что эти атрибуты представляют соотношение сторон изображения, хотя синтаксис остается прежним. Современные браузеры делят эти значения друг на друга, чтобы определить внутреннее соотношение сторон элемента img до отрисовки страницы. Это позволяет зарезервировать место, которое будет занимать изображение при отрисовке макета.

Как правило, в теге <img> всегда следует использовать атрибуты height и width со значениями, соответствующими исходному размеру изображения. При этом нужно указать height: auto вместе с max-width: 100%, чтобы переопределить высоту из HTML-атрибута.

<img src="image.jpg" height="200"> width="400" alt="…"
img {
  max-width: 100%;
  height: auto;
}

Используя атрибуты width и height в элементах <img>, вы сможете избежать высокого значения CLS из-за изображений.

Важно отметить, что у этого подхода нет недостатков, поскольку он опирается на давно устоявшееся поведение браузера – любой браузер с поддержкой базового CSS будет работать так же, как и всегда, а атрибуты height и width в вашей разметке будут переопределены вашими стилями.

Атрибуты width и height позволяют избежать проблем с CLS, резервируя необходимое пространство для изображений. Однако пользователям не нравится, когда на месте изображения показывается пустое место или плейсхолдер низкого качества, пока изображение загружается и отрисовывается. Хотя вы можете предпринять определенные действия, чтобы уменьшить измеримое и ощутимое влияние медленно загружающихся изображений, единственный способ быстрее представить пользователю полностью отрисованное изображение – это уменьшить его размер при передаче.

отрисовка самого крупного контента

Показатель Largest Contentful Paint (LCP) отражает время, необходимое для отрисовки самого крупного элемента контента, видимого в области просмотра пользователя, то есть элемента, который занимает наибольшую часть видимой страницы. На первый взгляд, это слишком специфический показатель, но он служит практическим индикатором момента, когда большая часть страницы уже отрисована с точки зрения пользователя. LCP – это важный показатель (воспринимаемой) производительности.

Такие показатели, как DOMContentLoaded или событие window.onload, могут быть полезны для определения того, когда процесс загрузки текущей страницы технически завершен, но они не обязательно соответствуют восприятию страницы пользователем. Небольшая задержка при отрисовке элемента за пределами области просмотра пользователя будет учтена в обоих этих показателях, но, скорее всего, останется совершенно незамеченной реальным пользователем. Если показатель LCP высок, то у пользователя может сложиться впечатление, что страница работает медленно или вообще не загружается.

Восприятие пользователем скорости загрузки, которое отражает показатель LCP, напрямую влияет на удобство сайта. Эксперимент, проведенный компанией Vodafone в прошлом году, показал, что улучшение LCP на 31 % не только привело к росту продаж на 8 % (что само по себе является хорошим результатом), но и увеличило на 15 % долю посетителей, ставших потенциальными клиентами, и на 11 % – долю пользователей, посетивших корзину.

Более чем на 70 % веб-страниц самым крупным элементом в исходной области просмотра является изображение – либо отдельный элемент <img>, либо элемент с фоновым изображением. Другими словами, у 70 % страниц показатель LCP зависит от изображений. Это неудивительно: крупные, привлекающие внимание изображения и логотипы, как правило, размещаются в верхней части страницы.

LCP, выделенная в консоли страницы web.dev

Чтобы избежать задержек LCP, во-первых, никогда не указывайте loading="lazy" для изображений в верхней части страницы, поскольку задержка запроса до отрисовки страницы, скорее всего, окажет сильное негативное влияние на показатель LCP. Во-вторых, с помощью fetchpriority="high" можно сообщить браузеру, что передача этого изображения должна быть приоритетной по сравнению с другими изображениями на странице.

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

Заключение

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

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

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