LCP под микроскопом: как выжать максимум из самой важной метрики Google

Страницы:  1

Ответить
 

Professor Seleznov


Довольно многие, кто близок к миру web разработки, не раз слышали про метрики web-vitals. По-настоящему значимыми они стали в середине 2021 года — в этот период Google официально стал учитывать метрики в ранжировании для мобильного поиска. С тех пор многие компании стремятся добиться хороших показателей метрик web-vitals. И, пожалуй, самая важная из этих метрик — LCP.
Привет! Меня зовут Николай, я — frontend-разработчик в компании Иви. В зоне моей ответственности как раз и лежит web-версия онлайн-кинотеатра. И в четвертом квартале 2025 года команда web решила сосредоточить ресурсы на метрике LCP. Что такое web-vitals в целом и LCP в частности?
Оглавление
Метрики web-vitals — что это?
Web-vitals — это инициатива Google, которая выделяет ключевые метрики для оценки пользовательского опыта на сайте. Если раньше были десятки сложных показателей, то web-vitals фокусируется на нескольких, самых важных.
Цель — дать единый, понятный язык для разработчиков, SEO-специалистов и руководителей, чтобы оценить, насколько быстро, отзывчиво и стабильно работает сайт для реальных пользователей.

Текущие ключевые метрики web-vitals

Ключевая тройка метрик меняется каждые несколько лет. Сейчас (2026) это:
  • LCP (Largest Contentful Paint) — «Как быстро загружается основное содержимое?» (Метрика загрузки)
  • INP (Interaction to Next Paint) — «Как быстро сайт реагирует на клики, тапы, нажатия клавиш?» (Метрика отзывчивости). (Примечание: заменил FID в 2024 году)
  • CLS (Cumulative Layout Shift) — «Насколько стабильно отображается страница, не "прыгает" ли контент?» (Метрика визуальной стабильности)
Почему им уделяют столько внимания?
  • Пользовательский опыт: Прямая связь с удовлетворенностью
  • SEO: Являются ранжирующим фактором в поиске Google
  • Бизнес-метрики: Хорошие web-vitals коррелируют с более высокой конверсией и вовлеченностью

Подробнее про метрику LCP
Простыми словами: LCP измеряет, через какое время самый большой и заметный элемент в видимой области экрана (viewport) становится полностью отрисованным. Это момент, когда пользователь видит, что «страница уже грузится» и появляется главный контент.
Что считается LCP-элементом?
  • Изображения (<img><image> внутри <svg>)
  • Постер-изображения внутри видео (<video> с poster)
  • Элементы с фоновым изображением, загруженным через url() (css свойство background-image)
  • Блочные элементы (<div><p><h1>) с текстовым узлом
Примеры с сайта Иви:
для главной страницы LCP-элементом является постер в слайдере:
pic
для доступного контента LCP-элементом является постер в плеере:
pic
пример, где LCP-элементом является текстовый узел (заголовок страницы):
pic
Что НЕ считается LCP-элементом?
  • Элементы, которые находятся за пределами видимой области
  • Слишком мелкие элементы — выбирается всегда самый большой
  • Анимированные или меняющиеся элементы
Пороги оценки LCP:
  • Хорошо (Good): ≤ 2.5 секунды
  • Требует улучшений (Needs Improvement): 2.5 – 4.0 секунды
  • Плохо (Poor): > 4.0 секунды


Инструменты для мониторинга LCP
Основным инструментом для мониторинга web-vitals метрик являются так называемые CrUX (Chrome User Experience) отчеты, которые строит Google. Эти отчеты находятся в открытом доступе и можно смотреть состояние метрик в принципе для любого сайта. Вот ссылка-пример такого отчета для сайта Иви:
https://cruxvis.withgoogle.com/#/?view=loadingperf&url=https%3A%2F%2Fwww.ivi.ru%2F&identifier=origin&device=PHONE&periodStart=0&periodEnd=-1&display=p75s
В качестве упражнения, попробуйте посмотреть CrUX отчеты ваших любимых сервисов.
pic
Главная панель метрики LCP
Тут можно обратить внимание на вкладку Controls — она позволяет гибко настраивать вывод графика метрик. Чем именно пользуется наша команда:
  • В фильтре Data мы глобально ориентируемся на Origin — данное значение показывает LCP для всех страниц сайта в целом
  • В фильтре Device — в первую очередь ориентируемся на мобильные устройства (Phone)
  • И также нас интересует 75 перцентиль — это показатель, сколько страниц сайта имеют определенное значение метрики
Решение сосредоточить силы команды было принято исходя как раз из этого отчета, и основной нашей задачей было улучшить LCP для мобильных устройств, потому что значение метрики «подбиралось» к желтой зоне (>2.5 секунд). Почему также не десктоп? А для десктопа у нас значение метрики было с хорошим запасом (по данным CrUX отчетов в районе ~1800ms):
pic
И еще одной причиной внимания именно к мобильным значениям метрики является инициатива Google, называемая mobile-first-indexing. Это подход, при котором для сканирования, индексации и ранжирования сайтов используется в первую очередь их мобильная версия, а не десктопная. Это означает, что контент, структура и технические параметры (скорость, адаптивность), доступные на смартфонах, определяют место сайта в поисковой выдаче. Подробнее тут — https://developers.google.com/search/docs/crawling-indexing/mobile/mobile-sites-mobile-first-indexing?hl=ru

Препарируем метрику LCP — из чего она состоит?
Для дальнейшего понимания и поиска узких мест надо разобраться, из чего же состоит метрика LCP и что именно показывают ее составляющие:
Метрику LCP составляют четыре «подметрики» в порядке их подсчета при загрузке страницы с LCP-элементом:
  • TTFB — Time to first byte — время от начала навигации до получения первого байта HTML-документа от сервера. Эта метрика показывает скорость работы бэкенда и сети. Важно отметить, что эта метрика также считается отдельной самостоятельной метрикой web-vitals, но при этом входит в конечный LCP
  • Resource Load Delay — задержка начала загрузки LCP-элемента. Это время между TTFB и моментом, когда браузер фактически начал скачивание LCP-элемента. Большая задержка означает, что более важный ресурс ждал, пока скачаются менее важные
  • Resource Load Duration — собственно время скачивания LCP-элемента. Тут все просто. На значение этой метрики влияет размер изображения, его степень сжатия, скорость работы сети и наличие кэша
  • Element Render Delay — это время между окончанием загрузки элемента и его финальной отрисовки на экране. На эту метрику может влиять опять же размер изображения (от этого зависит скорость его декодирования на CPU, особенно для более слабых по сравнению с ПК мобильных устройств); ожидание основного потока (Main Thread); ожидание стилей
Очень удобно, что CrUX отчет также предоставляет графики этих составляющих LCP, где можно отдельно проанализировать изменение в течение времени каждой из них:
pic

Анализ и выявление возможностей для оптимизации
Сейчас по логике я должен рассказать, как мы проводили анализ и выявляли куда двигаться, но я сделаю небольшое отступление. Параллельно с тем, что команда взяла задачу по улучшению метрики, один из наших коллег решил сделать эксперимент. Исторически сложилось так, что картинки на сайте Иви в большинстве своем были в формате JPEG, тем временем как формат WebP уже обзавелся внушительной поддержкой современными браузерами. Было принято решение провести эксперимент с заменой формата с JPEG на WebP. Для замеров использовался стенд — пустая страница с одним вариантом картинки из двух: A) JPEG B) WebP Результаты отражены в таблице ниже:
Перцентили LCP JPEG WebP Разница в процентах
p50 LCP (ms) 1628 1284 -21.1% 
p75 LCP (ms) 1752 1344 -23.3% 
p95 LCP (ms) 2140 1396 -34.8% 

Увидев такие хорошие результаты, было принято решение уже на самом сайте Иви заменить формат картинок, являющихся LCP-элементом (см. примеры с сайта Иви выше): на Главной странице сайта и на карточках контента. По итогу эксперимента увидели улучшение метрики для Главной страницы на десктопной версии на 45ms, на мобильной версии — 35ms. На карточках изменений не было, но результат в целом нас устроил и открыл дорогу к дальнейшим поискам возможностей оптимизации LCP. Увы, не всегда достаточно просто внедрить новую технологию, чтобы улучшить метрики. Так что копнем глубже.
Разобравшись с теоретической частью и вооружившись инструментами мониторинга, мы в первую очередь провели анализ LCP на сайте с большим вниманием к карточкам контента в контексте мобильной версии, так как карточки контента — это большинство страниц сайта Иви, и нам очень важна их скорость работы. С результатами замеров можно подробно ознакомиться в таблице ниже:
Тестируемое окружение — прод сайта Иви, проблемный web-mobile, сетевой кэш отключен, средние результаты по 5 замерам LCP в ms
«Легенда» таблицы:
  • TTFB: Time To First Byte
  • RLD: Resource Load Delay
  • RLDura: Resource Load Duration
  • ERD: Element Render Delay
  • LCP Total: TTFB + RLD + RLDura + ERD
Тип страницы Троттлинг TTFB RLD RLDura ERD LCP Total
Доступный к просмотру контент Нет 384 26 108 315 832
4xCPU + Slow 4G 381 343 2286 2100 5110
6xCPU + Slow 4G 1268 265 1843 2153 5529
20xCPU + Slow 4G 3060 365 5426 2205 11055
4xCPU + 3G 453 1750 8339 6646 17188
6xCPU + 3G 945 1784 9215 5663 17606
20xCPU + 3G 3125 2301 7598 5120 18144
Закрытый подпиской или покупкой контент Нет 380 16 179 279 854
4xCPU + Slow 4G 2509 354 3128 707 6698
6xCPU + Slow 4G 4250 338 3095 781 8464
20xCPU + Slow 4G 23129 512 2896 1187 27724
4xCPU + 3G 1783 3023 11401 2156 18362
6xCPU + 3G 293 4220 10047 5255 19814
20xCPU + 3G 40548 1864 10425 3194 56030
Так называемый «фейк» — карточки для SEO Нет 1940 11 140 1616 3706
4xCPU + Slow 4G 11054 403 1770 9995 23223
6xCPU + Slow 4G 17154 413 1737 10283 29587
20xCPU + Slow 4G 68414 740 1579 16769 87502
4xCPU + 3G 16351 1937 6607 33641 58535
6xCPU + 3G 26734 1718 6605 34438 69494
20xCPU + 3G 97682 2141 6256 45391 151470
Главная страница Нет 2171 40 103 84 2400
4xCPU + Slow 4G 1373 82 2745 2047 6257
6xCPU + Slow 4G 902 160 5675 32 6768
20xCPU + Slow 4G 854 206 5176 233 6469
4xCPU + 3G 843 1507 14197 2283 18828
6xCPU + 3G 844 1675 16557 482 19557
20xCPU + 3G 997 1336 13656 3317 19304

Также для облегчения анализа были сделаны дополнительные задачи (не направленные на прямое улучшение LCP). Основной задачей стало добавление графика разбивки метрики LCP в Grafana. Этот график строится на основе отправляемых данных LCP в нашу аналитическую систему. Основное отличие от графиков в CruX отчетах заключается в том, что этот график обновляется в режиме реального времени, что обеспечивает команде веба непрерывный мониторинг и анализ метрики, и в случае негативных изменений позволяет оперативно реагировать на ухудшение. Как пример — несколько раз при проблемных релизах мы очень быстро выявляли проблему и откатывали релиз, не дожидаясь пересчета метрики со стороны Google. Скрин для понимания:
pic
Дополнительно был проведен ручной анализ DOM дерева на предмет оптимизаций LCP.
По результатам анализа были сформулированы и реализованы следующие задачи (помимо упомянутого выше эксперимента с WebP):
  • До начала работ по LCP на карточках контента LCP-элементом у нас являлись теги div с background-image. Гипотеза состояла в том, что если перевести LCP-элемент на тег image и обвесить его специальными атрибутами (fetchpriority = high и loading = eager), то можем получить некоторое улучшение LCP. Атрибут fetchpriority со значением high как бы говорит браузеру — этот ресурс надо загрузить как можно скорее, а атрибут loading со значением eager прямо указывает, что изображение должно загрузиться немедленно, в отличие от значения lazy. По итогам никакого улучшения не было выявлено, LCP остался в тех же значениях.
  • Далее решили продолжать копать тему с тегом img и решили расширить этот тег тегом picture. Тут гипотеза состояла в том, что у нас что для десктопа, что для мобильных устройств отдавалась одна и та же по размерам картинка в довольно большом разрешении. Решили добавить респонсивные постеры с помощью тега picture. Целями опять стали LCP картинки на Главной и на карточках контента. По результатам получили небольшое улучшение LCP (~35-50ms) на всем сайте.
  • Благодаря задаче с выводом составляющих LCP в графане заметили, что Element render Delay довольно высок, чтобы быть нормой. Решили копать в эту сторону дальше. Одной из предполагаемых причин было то, что у нас слишком загруженный Main Thread, но раскопки с использованием Perfomance в Chrome ни к чему не привели. Тогда решили зайти с другой стороны, не разбираться в кишках всего приложения и искать проблему там, а создать тестовый стенд и начать пошагово навешивать туда функционал, который в теории может замедлять Element Render Delay.
Возможно, тут возникнет вопрос — а было ли что-то по TTFB? Ответ — да, коллеги из нашей команды параллельно работали над улучшением кэширования для всего сайта. Вкратце, это ускорило TTFB и соответственно LCP по данным из аналитической системы. Впрочем, это тема для отдельной статьи, и возможно в будущем мы про это расскажем (увлекательная получится история, следите за обновлениями!).

Прицельно бьем в Element Render Delay
Вследствие неудачи ресерча ERD, решили сделать стенд — начать с простого html файлика (без экосистемы React) с картинкой (которая будет считаться как LCP-элемент) и постепенно добавлять туда разный функционал, который в теории может ухудшать или улучшать время Element Render Delay. Условия эксперимента — mobile, без учета троттлинга процессора и сети, изначально используется картинка с нашего CDN; также создан вспомогательный скрипт в head, который находит LCP-элемент и вытаскивает из него Element render delay. Далее делаем 15 замеров (перезагрузок страницы) — и скрипт выведет средний ERD. Эксперименты и результаты собраны в табличке под катом (уж очень внушительной она оказалась):

Эксперименты и результаты

Эксперимент/гипотеза Описание гипотезы Результат ERD по 15 замерам Вывод
картинка в теге img в формате
JEPG без атрибутов оптимизации
посмотреть, как считается ERD, когда нет ничего в теории блокирующего ERD  📊 Средний LCP: 284 мс
⏱️ Средний ERD: 28 мс
📈 Средний ERD%: 10,3%
✅ ОТЛИЧНО: Нормальный уровень ERD
Без блокирующих в теории фич ERD в рамках нормы
тегу img добавлены атрибуты размеров возможно добавление таких атрибутов ускорит отрисовку картинки браузером 📊 Средний LCP: 568 мс
⏱️ Средний ERD: 344 мс
📈 Средний ERD%: 19,3%
✅ ОТЛИЧНО: Нормальный уровень ERD
Улучшения ERD не выявлено
картинка с другого источника, размеры те же предполагается, что есть проблемы с нашим CDN В пределах нормы По сравнению с другим источником наш CDN отдает картинку быстрее
конвертация JPEG в WebP проверить, как повлияет изменение формата на ERD 📊 Средний LCP: 297 мс
⏱️ Средний ERD: 32 мс
📈 Средний ERD%: 12,0%
✅ ОТЛИЧНО: Нормальный уровень ERD
На ERD изменение формата на WebP существенно не влияет
добавление атрибутов fetchpriority=high и loading=eager у тега img проверить, оказывают ли эти атрибуты влияние на ERD 📊 Средний LCP: 281 мс
⏱️ Средний ERD: 33 мс
📈 Средний ERD%: 11,9%
✅ ОТЛИЧНО: Нормальный уровень ERD
На ERD добавление атрибутов не оказывает эффекта
добавление в head медленных шрифтов  медленные шрифты могут тормозить ERD 📊 Средний LCP: 281 мс
⏱️ Средний ERD: 31 мс
📈 Средний ERD%: 11,6%
✅ ОТЛИЧНО: Нормальный уровень ERD
Медленные шрифты не тормозят ERD
добавление "тяжелых" css вычислений в head тяжелые вычисления css могут тормозить ERD 📊 Средний LCP: 280 мс
⏱️ Средний ERD: 29 мс
📈 Средний ERD%: 10,9%
✅ ОТЛИЧНО: Нормальный уровень ERD
Также критичного ухудшения ERD не замечено
добавление тяжелого скрипта для создания long task тяжелые long task могут тормозить ERD ERD ухудшился long task ухудшают ERD примерно на время их выполнения
добавление микротасок Множество микротасок могут ухудшать ERD.
Эксперимент запускался сначала с 60 микротасками, потом с 100, потом с 1000, потом без микротасок
В пределах нормы Микротаски никак не влияют на ERD — на разных кол-вах микротасок изменений ERD нет вообще
добавление счетчиков GTM, Яндекс Метрики и тп как на сайте на КК выполнение скриптов аналитики может тормозить ERD В пределах нормы Счетчики аналитики никак не влияют на ERD
добавление бандла css проверить, оказывают ли влияние наши бандлы на ERD; Добавление в том же порядке, что и на кк (в head) В предалх нормы бандл css не влияет на ERD
добавление бандла js В пределах нормы внезапно, но бандл js + бандлы для его работы (react ecosystem, web cypher) не влияют на ERD
добавление бандла плеера css В пределах нормы На ERD css бандл плеера не влияет
добавление бандла плеера js В пределах нормы Тут влияния бандла на ERD также нет
Блок бандлов через Charles Посмотреть как влияет блокировка бандлов на ERD Негативные изменения ERD Если заблокирован только бандл css — сильно ухудшается ERD (на время блокировки примерно)
Если заблокирован только бандл js — LCP в целом считается и отправляется по лого в шапке
Если заблокированы оба бандла — LCP не считается ни в Perfomance tab, ни в расширении web-vitals хрома, не отправляется в грут после взаимодействия со страницей; отправляется кастомный LCP

Зовем на подмогу — дополнительные эксперименты при помощи Charles
Из всех экспериментов на стенде «удался» — то есть показал явное влияние на ERD — эксперимент с блокировкой загрузки основных бандлов через Charles.

Блокировка основного js бандла
Подробнее опишу кейс, который был найден с помощью Charles. Мы обратили внимание на наши основные js и css бандлы. В них собраны скрипты и стили, которые нужны на всех разделах иви. Далее решили посмотреть, а что происходит, если загрузку этой статики «подвесить» в Charles, и увидели интересное поведение — при блокировке js бандла во вкладке Network у нас также подвисали два css файла для шапки сайта, а также для кнопки «Открыть» в приложении. Нюанс этих блоков в том, что их css лежит рядом с ними, а не в теге head. Это следствие реализации этих компонентов как Lazy-блоков. При этом эти блоки находились ДО блока, внутри которого весь основной контент страницы, включая LCP-элемент. Для понимания скрин DOM до оптимизации:
  • Файл со стилями шапки
  • Блок шапки, генерирующий css рядом с собой
  • Стили кнопки Открыть в приложении
  • Враппер, в котором лежит блок с LCP-элементом
pic
И при этом, до тех пор, пока эти два css файла не зарезолвились, мы наблюдали пустую страницу с фоном. Исходя из этого родилась задача — просто перенести эти блоки ниже блока с LCP-элементом, а стилями визуально сделать так, как будто переноса не было. Но к сожалению оказалось, что этот вариант оптимизации в отношении шапки сайта нам не подходит, так как в теории перенос шапки сильно сломает SEO. Пришлось откатить правки и подумать над другим решением. Обратили внимание, что именно Lazy рельсы компонента создают его css файл рядом. Поэтому решили сделать шапку обычным компонентом — стили шапки стали собираться в общем css бандле. Блок кнопки Открыть в приложении оставили после враппера. По итогу это почти простое решение дало очень мощный выхлоп — значительное улучшение метрики LCP на всем сайте в целом и на основных разделах в частности: ~200-250ms для Mobile, ~150-200ms для Desktop. Это подтвердилось как на наших внутренних графиках, так и на CrUX отчетах.

Блокировка основного css бандла
Воодушевленные таким успехом, мы решили повторить эксперимент с подвисанием, только в этот раз с бандлом стилей. В этом кейсе все остальные скрипты и стили продолжали загружаться, но тем не менее, пока css бандл был в состоянии pending, на странице не было видно LCP-элемента. При снятии блокировки в charles LCP-элемент появлялся, а сама метрика, а конкретно ее составляющая Element Render Delay считалась примерно в ТО ЖЕ время, на которое была заблокирована загрузка css бандла. По результатам этого эксперимента родилась задача — сделать так, чтобы css бандл не блокировал рендер DOM дерева, а также добавить critical.css (или skeleton.css), который был бы легковесным и его скачивание занимало гораздо меньше времени, чем скачивание основного бандла. В рамках эксперимента сделали это только для карточек контента и только на мобильной версии сайта, под аб-тестом. По итогу зафиксировали значительное улучшение метрики LCP на mobile (~100-110ms), а конкретно составляющий LCP — Element Render Delay. Другие составляющие LCP без изменений (что, собственно, и ожидалось).

Из желтой зоны в зеленую —  итоги наших оптимизаций
До начала экспериментов по данным CrUX LCP для мобильных устройств подбирался к желтой зоне и даже в определенные временные промежутки попадал в нее, в пике значение было 2521ms. Но в итоге нашими экспериментами удалось снизить это значение на 419ms, до 2102ms по последним данным CrUX, в пересчете на проценты ~17%. Считаем это хорошим результатом как по абсолютным цифрам, так и по относительным. При этом стоит отметить, что мы пришли к выводу, что именно со стороны клиента возможности оптимизации мы исчерпали.
Приведу рекомендации тем разработчикам, которые либо планируют, либо уже занимаются оптимизацией LCP:
  • CrUX и его показатели — ваш основной ориентир
  • Очень удобно настроить на своей стороне инструменты мониторинга — обязательно сделайте это!
  • Нащупайте больные места вашей LCP, используя анализ подметрик — это покажет, в каких местах у вас проблемы. Для нас это стали показатели Element Render Delay и TTFB
  • Следите за LCP-картинками — мир веб-разработки развивается стремительно, даруя новые возможности для оптимизации их загрузки
  • Проанализируйте поведение ваших бандлов/скриптов при различных кейсах — велика вероятность их прямого влияния на LCP
На этом мой рассказ подходит к концу. Надеюсь, он был полезен для вас. Желаю вам удачи в ваших экспериментах!-Источник
 
Loading...
Error