В прошлой части мы разобрали, как loading="lazy" перестаёт работать в скрытых элементах. Но и в обычной вёрстке он не всегда делает то, что от него ждут. Три ситуации, когда ленивая загрузка не спасает, и одна, когда она прямо вредит.
Это двадцать третья часть цикла «PageSpeed без мифов».
1. Лента в одну колонку на телефоне
Ленивая загрузка Chrome начинает качать картинку задолго до экрана — с запасом в тысячи пикселей, особенно на медленной сети. Когда карточки идут в одну колонку одна под другой, в этот запас попадает десяток картинок сразу.
На мобильной ленте одного сайта до первой отрисовки уходило 774 КБ картинок. После перехода на свою загрузку — адреса в data-src, подстановка через IntersectionObserver с запасом в половину экрана и только после ворот из восьмой части — 513 КБ.
2. Слайдеры вплотную к экрану
Слайдер, начинающийся сразу под первым экраном, — в зоне ленивой загрузки с первого кадра. Его картинки грузятся вместе с первым экраном, хотя посетитель их ещё не видит.
3. Соседние слайды
Слайдер на первом экране показывает один слайд, но соседние часто уже в вёрстке, хоть и за краем. Браузер считает их «рядом» и грузит. Хуже того — сколько соседей успеет попасть в окно, зависит от скорости конкретной загрузки: на одном и том же билде окно первой отрисовки прыгало между 335 и 432 КБ. Это лишние 0,4 секунды к LCP в модели и заодно источник разброса оценки (четвёртая часть).
Лечение — отложенные адреса у всех слайдов, кроме видимого, с подстановкой после ворот и при переключении слайда. Подробно — в следующей части.
Когда lazy вредит: картинка первого экрана
Самая частая ошибка — повесить loading="lazy" на все картинки шаблоном, включая главную картинку первого экрана. Браузер откладывает её загрузку до расчёта вёрстки, и в фазах LCP появляется «задержка загрузки ресурса» — у нас 1,8 секунды.
Картинке, которая станет LCP, нужно обратное:
<link rel="preload" as="image" href="/img/hero.avif" fetchpriority="high">
<img src="/img/hero.avif" width="1600" height="900" alt="…"
loading="eager" fetchpriority="high">
loading="eager"(или без атрибута) — грузить сразу;fetchpriority="high"— и на прелоаде, и на самой картинке: браузер поставит её в начало очереди;- прелоад — если адрес картинки браузер узнаёт поздно (например, она внутри компонента, который рисуется скриптом).
Только одна-две картинки. Высокий приоритет на десяти картинках — это снова «всё срочно», и они начнут толкаться в канале с CSS и шрифтами.
Правило
Первый экран — eager и высокий приоритет. Близко под первым экраном и в слайдерах — свой контроль загрузки через ворота. Далеко внизу — обычный lazy справится. И всегда — размеры у каждой картинки (двадцать первая часть).
Не уверены, какие картинки у вас грузятся раньше времени?
Пришлите адрес — разберу окно первой отрисовки и картинки в нём.
// загружаю комментарии…