awesome-everything EN
↑ Обратно к восхождению

Браузер и фронтенд-рантайм

LCP: четыре фазы, одна доминирующая стоимость

Суть Largest Contentful Paint раскладывается на TTFB, задержку загрузки ресурса, время загрузки ресурса и задержку рендера — диагностировать и починить правильную фазу и есть вся игра.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 14 min

Команда подключает CDN, сжимает hero-картинку — и LCP почти не двигается. Проблема была не в размере картинки — браузер обнаруживал её поздно, после выполнения JS-бандла. Фикс — один атрибут в HTML. LCP ломается четырьмя разными способами, и только один фикс работает на каждую фазу.

Что измеряет LCP и когда он срабатывает.

Largest Contentful Paint — время отрисовки самого крупного contentful-элемента, видимого во вьюпорте во время загрузки. «Контент» — конкретный список: <img>, постер <video>, фоновое изображение через url(), блочные элементы с текстом. Браузер наблюдает за элементами по мере их отрисовки, обновляет кандидата на «самый крупный» и финализирует LCP на первом взаимодействии пользователя (после того как пользователь взаимодействует, дальнейшая «загрузка» уже не загрузка). На большинстве страниц LCP-элемент — hero-картинка или главный заголовок.

Четыре фазы.

Время LCP — это сумма четырёх последовательных частей. Фикс разный для каждой.

  1. TTFB — время до первого байта от сервера. Причины: медленный SSR, нет CDN, медленный запрос к базе на пути рендера. Фикс: кеш, CDN, вынести медленные загрузки данных с пути рендера (streaming SSR с Suspense-границей).

  2. Resource load delay — зазор между TTFB и началом загрузки LCP-картинки браузером. Причина: браузер обнаруживает картинку поздно — она ссылается только в CSS или инжектируется JS, не в начальном HTML, preload-сканер её не видит. Фикс: поместить LCP-картинку в начальный HTML как обычный <img> с fetchpriority="high" или <link rel="preload">.

  3. Resource load time — сколько сама LCP-картинка скачивается. Причина: огромный файл, неправильный формат, не сжата. Фикс: правильный формат (AVIF, WebP), корректный размер для вьюпорта через srcset, сжатие.

  4. Element render delay — зазор между окончанием скачивания картинки и её отрисовкой. Причина: render-blocking CSS или JS всё ещё занимает главный поток после готовности картинки. Фикс: инлайн критического CSS, defer некритичного JS.

Четыре фазы LCP
TTFB
Сервер + CDN + БД
Resource load delay
Зазор обнаружения в HTML/CSS/JS
Resource load time
Размер файла × скорость соединения
Element render delay
Render-blocking ресурсы

Preload-сканер — почему обнаружение решает всё.

Браузеры запускают вторичный парсер — preload-сканер — который обгоняет основной HTML-парсер в поиске ресурсов для загрузки, даже пока основной парсер заблокирован скриптом. Именно поэтому <img> в начальном HTML грузится рано: сканер видит его и немедленно стартует загрузку. И именно поэтому картинка, ссылающаяся только в CSS (background-image) или инжектируемая JS, грузится поздно: сканер её не видит — картинка не обнаруживается, пока CSS не парснется или JS не выполнится.

Глубинная причина, почему «поместить LCP-картинку в HTML» работает: только в HTML preload-сканер может её найти без ожидания. fetchpriority="high" затем поднимает ту загрузку выше других ранних ресурсов; <link rel="preload"> — тяжёлая артиллерия для ресурсов, которые сканер всё равно не видит.

Самая частая самонанесённая LCP-регрессия.

Добавление loading="lazy" на hero-картинку. Lazy loading существует для defer-а картинок ниже сгиба — тех, до которых пользователь ещё не доскроллил. Применить его к hero означает сказать браузеру отложить загрузку ровно той картинки, которую таймит метрика LCP. Результат — почти всегда большой resource load delay, которого раньше не было. Никогда не lazy-load-ьте LCP-элемент.

Почему это работает

Частая ошибка — сжимать картинку, когда реальная проблема — load delay. Если resource load delay — доминирующая фаза (браузер обнаруживает картинку поздно), даже файл в 10× меньше не сдвинет LCP — задержка до начала загрузки остаётся бутылочным горлышком. Дисциплина: сначала прочитать разбивку по фазам (доступна из LCP attribution web-vitals библиотеки или DevTools), затем чинить доминирующую фазу. Применить неправильный фикс — потратить усилия впустую и оставить число плохим.

Викторина

Hero-картинка — LCP-элемент, и LCP плох. У картинки loading='lazy'. В чём вероятная проблема?

Викторина

Время LCP доминируется 'resource load delay' — зазором между TTFB и началом скачивания картинки. Какой фикс целит в эту фазу?

Расставь шаги по порядку

Расставьте четыре фазы времени LCP — от запроса, покидающего браузер, до отрисовки LCP-элемента.

  1. 1 TTFB — сервер производит и отправляет первый байт
  2. 2 Resource load delay — браузер обнаруживает и начинает загрузку LCP-картинки
  3. 3 Resource load time — LCP-картинка скачивается
  4. 4 Element render delay — картинка рисуется после очистки render-blocking работы
Вспомните перед уходом
  1. 01
    Назовите четыре фазы времени LCP и что делает каждую медленной.
  2. 02
    Почему помещение LCP-картинки в начальный HTML помогает LCP, и что добавляет fetchpriority='high'?
  3. 03
    Команда замеряет разбивку по фазам LCP и находит: load delay 80 мс, resource load time 3.5 с. Какую фазу чинить первой и как?
Итог

LCP измеряет время отрисовки самого крупного contentful-элемента во вьюпорте и раскладывается на четыре последовательных фазы: TTFB, resource load delay, resource load time и element render delay. Фикс работает только если целит в доминирующую фазу — сжать картинку, когда бутылочное горлышко в load delay, ничего не даст. Preload-сканер — причина, почему размещение картинки в начальном HTML важно: только HTML-встроенные картинки видны сканеру до выполнения blocking-скриптов. Никогда не применяйте loading="lazy" к LCP-элементу — это добавляет load delay к ровно измеряемому элементу. Полная разбивка по фазам доступна из LCP attribution библиотеки web-vitals или DevTools performance-трассы — прочитать её перед любым фиксом это дисциплина, которая отделяет быструю итерацию от потраченных усилий.

Связанные уроки
встречается в193
Продолжить восхождение ↑INP: input delay, processing, presentation
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.