Отложенная загрузка ресурсов
Подсказки прошлого урока помогали раньше обнаружить необходимый файл. Но большая статья содержит и ресурсы, которые нужны только после прокрутки. Получать их одновременно с первым абзацем бывает нецелесообразно. В этом уроке проведём границу отложенной доставки и проверим, что читатель по-прежнему получает весь материал.
Используем нижнюю галерею advanced/resource-lab. Три собственные SVG-схемы имеют разные адреса и известные размеры. Это маленькие учебные файлы; их вес не моделирует фотографии ProfessorWeb. Стенд не запускался автором. Результат урока — обоснованный выбор момента загрузки, а не заранее заявленное уменьшение LCP.
Что откладывается
Lazy loading относится к получению ресурса, который ожидается позднее. Он не означает удаление абзацев из статьи, скрытие ссылки или остановку всей программы. Если текст нужен сразу, его следует сохранять доступным в документе. Изображение ниже длинного объяснения может иметь другой момент доставки, не меняя содержание самого объяснения.
Разделите ресурсы по пользовательскому сценарию. Главное изображение на первом экране рассматривается вместе с LCP. Нижние схемы нужны после прокрутки. Дополнительный виджет может требовать явного действия. Одинаковый атрибут на всех изображениях игнорирует эти различия. Для основного LCP-ресурса искусственное ожидание противоречит задаче раннего показа.
В учебной странице у галереи есть большой отступ, чтобы её положение легко исследовать. Это условие стенда, а не рекомендация оформления статьи. В настоящем документе положение определяется содержанием, шириной окна и размером текста. Поэтому классификацию нельзя сделать только по номеру картинки: один и тот же элемент на разных экранах окажется в другой области.
Native lazy loading изображений
Атрибут loading="lazy" предлагает браузеру отложить изображение до выбранного им расстояния от видимой области. Расстояние не задаётся автором этим атрибутом и может отличаться между условиями. Поэтому запрос до появления изображения на экране сам по себе не означает поломку. Текущая семантика приведена в MDN: img loading.
Первый элемент галереи выглядит так:
<img src="../assets/lower-one.svg"
width="640" height="320" loading="lazy"
alt="Круг: первая учебная схема">
Это полный элемент из стенда. Размеры задают известное отношение сторон, а CSS вписывает картинку в колонку. Даже до доставки браузер получает основание для размещения. Альтернативный текст сохраняет смысл при недоступном ресурсе. Отложенная доставка не освобождает автора от договора геометрии и содержательного описания.
Для независимого сравнения скопируйте страницу и измените только loading выбранной нижней картинки на eager. Остальные картинки, стили и подсказки должны остаться прежними. Откройте обе версии при одинаковых условиях. Тогда можно изучить изменение момента доставки одного ресурса, сохранив его качество и размеры.
Прокрутка является частью проверки
Сначала исследуйте загрузку без прокрутки. Затем отдельной сессией выполните одинаковое движение к галерее. Смотрите, когда начинается запрос, когда ресурс готов и когда изображение становится доступным в нужном месте. Быстрый первый экран полезен, но пустое ожидание при каждом следующем рисунке требует отдельной оценки.
Зафиксируйте темп прокрутки. Медленное чтение и быстрый переход к низу страницы создают разные условия. Если в одной версии человек задержался на абзаце, а в другой сразу прыгнул к рисунку, сравнение меняет не только настройку доставки. Сохраняйте эти сценарии отдельно, как мы делали с навигацией и состоянием кеша.
Не вычисляйте эффективность по одному общему событию load. Отложенные изображения имеют особенности участия в нём, поэтому оно не означает, что все будущие рисунки уже доступны. Важно наблюдать конкретный ресурс и его показ. Иначе новая более ранняя граница события будет выглядеть как ускорение всего учебного материала, которого эксперимент не установил.
Режим scripting также входит в условия. Нативное откладывание изображения применяется при включённом JavaScript; при другом режиме браузер может получать ресурс иначе. Это свойство описано в той же документации img. Оно отличается от самодельной схемы, которая хранит адрес только в data-src и вообще не имеет рабочего пути без исполнения программы.
Размер и пустая область
У нижней картинки заранее известны ширина и высота. При неизвестных размерах появляется дополнительная проблема: поздний ресурс может изменить расположение уже читаемого текста. Механизм сдвига разобран в уроке о CLS. Здесь сохраняем геометрию, чтобы не смешивать стоимость доставки с потерей места чтения.
Если вместо рисунка показывается заглушка, её размеры должны соответствовать будущему содержимому. Нельзя резервировать произвольную короткую полоску, а затем вставить высокий документ. И нельзя обрезать полезное изображение ради сохранения старой высоты. Договор должен отражать реальные варианты ресурса, которые предусмотрены статьёй.
Проверьте увеличение текста и узкую колонку. Рисунок окажется дальше от начала страницы, а подпись может занимать больше строк. Поэтому решение о моменте запроса должно выдерживать не только один снимок широкого окна. Сохранённые атрибуты размеров помогают, но не заменяют проверку композиции и альтернативного текста.
Отложенная инициализация функции
Для компонентов, которым недостаточно атрибута изображения, можно исследовать IntersectionObserver. Он сообщает об изменении пересечения элемента с выбранной областью. Положительный rootMargin расширяет её и позволяет начать работу до входа в viewport. Это не измерение внимания пользователя и не доказательство прочтения. Назначение API описано в MDN: Intersection Observer.
Следующая самостоятельная вспомогательная функция показывает однократный сигнал. Она не включена в готовый resource-lab; вызываемое действие передаётся читателем отдельно:
function observeApproach(target, action) {
if (!("IntersectionObserver" in window)) return false;
const observer = new IntersectionObserver(entries => {
if (!entries.some(entry => entry.isIntersecting)) return;
observer.disconnect();
action();
}, { rootMargin: "200px" });
observer.observe(target);
return true;
}
Двести пикселей — учебный запас, а не измеренный оптимум. Если функция вернула false, нужен другой доступный путь: например, явная кнопка. Обработчик пересечения также не гарантирует успешной доставки компонента. Состояния ожидания, ошибки и повторной попытки остаются частью интерфейса, как при обычном запросе.
В нашем стенде виджет загружается только кнопкой. Такой договор проще: действие читателя запускает локальный модуль, а без действия запрос не нужен. Автоматическое включение при приближении будет отдельным изменением продукта. Не вводите его одновременно с исправлением изображений, иначе нельзя будет объяснить новую конкуренцию за сеть и основной поток.
Граница полезного откладывания
Если функция необходима для основной навигации или раскрытия текста, её поздняя доступность может мешать завершению задачи. Поэтому решение зависит от назначения компонента. Обязательная кнопка перехода и необязательный большой виджет не должны автоматически получать одинаковый режим. Сначала назовите, что человек ожидает сделать при входе на страницу.
Сохраните две записи: первый экран и получение нужного ресурса после прокрутки или явного действия. Укажите размеры, доступный запасной результат и условия сравнения. В следующем уроке применим такую границу к сторонним зависимостям: их стоимость включает не только передачу файла, но и всё исполнение, которое начинается после доставки.