Ленивая загрузка – это выжидательный подход к работе с ресурсами, когда загрузка ресурса откладывается до момента, пока он фактически не понадобится. В таком случае при работе с критически важными ресурсами экономятся данные, а также снижается конкуренция за эти данные при работе по сети. Такой прием стал веб-стандартом в 2019 году, а сегодня loading=«lazy» для изображений поддерживается в большинстве крупных браузеров. На словах все отлично, но случается ли перебор с ленивой загрузкой?

В этом посте обобщены и проанализированы данные о прозрачности веба, взятые в открытых источниках, а также проделано импровизированное A/B тестирование. Эта работа помогает понять производительность и степень внедрения нативной ленивой загрузки при работе с картинками. Оказывается, ленивая загрузка может быть поразительно эффективна при избавлении от ненужных картиночных байт, но, если с ней переусердствовать – это плохо скажется на производительности. А именно: наше исследование показывает, что при более жадной загрузке изображений в пределах первичной области видимости – в сочетании с более свободной и ленивой загрузкой остальных – достижима золотая середина. Экономится количество загруженных байт и улучшаются показатели Core Web Vitals.

Внедрение


По данным за июнь 2021 года из HTTP Archive, нативная ленивая загрузка изображений используется на 17% сайтов, и этот показатель быстро растет. Такой обширный плацдарм – впечатляющее достижение для относительно нового API.

image
Разбивка по типам сайтов,
использующих нативную ленивую загрузку изображений
(источник)
Запросив сырые данные из проекта HTTP Archive, яснее понимаем, к каким категориям относятся те сайты, за счет которых усваивается эта технология: 84% сайтов, использующих нативную ленивую загрузку изображений, работают на WordPress, 2% — на других CMS, а оставшиеся 14% не используют известных CMS. Эти результаты ясно демонстрируют, что именно WordPress является локомотивом внедрения этой технологии.

image

Разбивка по типам сайтов,
использующих нативную ленивую загрузку изображений.
(Источник)
Также стоит упомянуть о скорости внедрения. Еще в июле 2020 года количество сайтов на WordPress, применявших ленивую загрузку, исчислялось десятками тысяч в корпусе примерно из 6 миллионов ресурсов (1% от целого). С тех пор в одном только WordPress область внедрения ленивой загрузки расширилась более чем до 1 миллиона (14% от целого).

Корреляция производительности


Если подробнее разобраться в HTTP-архиве, то можно сравнить сайты, использующие и не использующие ленивую загрузку, сопоставив их метрику LCP (скорость загрузки основного контента). Данные LCP взяты из реального пользовательского опыта по отчетам Chrome User Experience Report (CrUX), а не получены синтетическим лабораторным тестированием. Ниже использован график с усами, визуализирующий распределения 75-й перцентили LCP по каждой из страниц: линии соответствуют 10-й и 90-й перцентилям, а прямоугольники – 25-й и 75-й перцентилям.

image

Распределение 75-й перцентили по показателю LCP на всех страницах,
в зависимости от использования нативной ленивой загрузки изображений.
(Источник)
У медианной страницы без ленивой загрузки 75-я перцентиль LCP составляет 2,922 мс, для сравнения: тот же показатель у страницы с ленивой загрузкой равен 3,546 мс. Таким образом, сайты, использующие ленивую загрузку, показывают сравнительно слабую производительность по LCP.

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

image

Распределение 75-й перцентили по показателю LCP на всех страницах WordPress, в зависимости от использования нативной ленивой загрузки изображений.
(Источник)
К сожалению, тот же паттерн просматривается, если углубленно изучить страницы WordPress; на тех из них, где используется ленивая загрузка, показатели скорости загрузки основного контента ниже. Медианная страница WordPress без ленивой загрузки имеет 75-ю перцентиль LCP в 3,495 мс, по сравнению с 3,768 мс у медианной страницы с ленивой загрузкой.

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

Условная производительность


Цель A/B-тестирования – подтвердить или опровергнуть следующую гипотезу: нативная ленивая загрузка изображений в том виде, как она реализована в ядре WordPress, приводит к снижению производительности по показателю LCP и позволяет передать меньше байт изображения. При этом тестировался демонстрационный сайт WordPress с темой twentytwentyone. Были протестированы как архивный, так и одностраничный тип (домашняя страница, страница со статьей). Тестирование проводилось как на ПК, так и на эмулированных мобильных устройствах при помощи WebPageTest. Каждая комбинация страниц тестировалась как с включенной, так и с отключенной ленивой загрузкой. Каждый тест проводился 9 раз, чтобы получить медианное значение LCP и количество байт изображения.

image

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

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

image

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

Можно так резюмировать результаты A/B тестирования: техника ленивой загрузки, используемая в WordPress, помогает ужать размер изображения в байтах, но за счет отложенной LCP.

Тестирование правок


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

С учетом этих новых данных были внесены экспериментальные правки, позволяющие обходиться без ленивой загрузки картинок, находящихся в верхней части страницы. Правки были проверены в тех же условиях, в которых проводился первый A/B тест.

image

Эти результаты выглядят гораздо оптимистичнее. Если применять ленивую загрузку только к изображениям, находящимся в нижней части окна, то регресс LCP можно полностью обратить вспять и даже добиться некоторого улучшения по сравнению с полным отключением LCP. Как же можно добиться еще более высокой скорости, чем вообще без ленивой загрузки? Одно из объяснений заключается в том, что, не применяя ленивую загрузку, удается снизить конкуренцию за каналы связи (network contention).

image

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

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

Выкатываем результат


Итак, вот мы и выяснили, как лучше организовать ленивую загрузку изображений, что приводит к экономии трафика на изображениях и повышению производительности LCP. Как же добиться, чтобы эта практика начала применяться на сайтах? Наиважнейшее изменение – внести патч в ядро performance WordPress, который позволил бы внедрить эти экспериментальные правки. Также при этом требуется обновить руководство по ленивой загрузке на уровне браузеров в -CMS, пояснив в нем, чем плоха ленивая загрузка изображений в верхней части экрана, и как CMS могут избегать ее, если будут опираться на соответствующую эвристику.

Поскольку эти наилучшие практики применимы ко всей веб-разработке в целом, логично было бы помечать и антипаттерны ленивой загрузки в таких инструментах как Lighthouse. Соответствующий запрос на спецификацию выложен на GitHub. Пока же единственное, что могут сделать разработчики для выявления лениво загружаемых элементов LCP – это организовать более тщательное журналирование данных, фигурирующих в полях на странице.

new PerformanceObserver((list) => {
  const latestEntry = list.getEntries().at(-1);

  if (latestEntry?.element?.getAttribute('loading') == 'lazy') {
    console.warn('Warning: LCP element was lazy loaded', latestEntry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

Вышеприведенный фрагмент кода на JavaScript оценит наиболее свежий элемент LCP и запишет в лог предупреждение, если этот элемент лениво загружается.

Также так подчеркивается передний край ленивой загрузки как метода и потенциал улучшения API на уровне платформ. Например, в Chromium предлагается поэкспериментировать с нативной жадной загрузкой некоторых первых изображений (примерно в соответствии с предложенными здесь правками), несмотря на значение атрибута loading.

Заключение


Если на вашем сайте нативно применяется ленивая загрузка изображений, проверьте, как именно она реализована и проведите A/B-тестирование, чтобы проверить, как такая загрузка сказывается на производительности. Возможно, вы выиграете, если станете жадно загружать картинки в верхней части страницы. Если ваш сайт работает на WordPress, то, возможно, вскоре появится или уже есть соответствующий патч для ядра WordPress. Если вы пользуетесь другой CMS, то убедитесь, что учитываете потенциальные проблемы с производительностью, описанные в этом посте.

Комментарии (1)


  1. AlexTOPMAN
    27.09.2022 08:59

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

    Имхо.