Исторически сложилось так, что веб-разработчикам было непросто измерить, насколько быстро основное содержимое веб-страницы загружается и становится видимым пользователям. Старые метрики, такие как загрузка или DOMContentLoaded, не работают должным образом, поскольку они не обязательно соответствуют тому, что пользователь видит на своем экране. А новые, ориентированные на пользователя показатели производительности, такие как First Contentful Paint (FCP), фиксируют только самое начало процесса загрузки. Если на странице отображается заставка или индикатор загрузки, этот момент не очень важен для пользователя.
Раньше мы рекомендовали метрики производительности, такие как Первая значимая отрисовка (FMP) и Индекс скорости (SI) (оба доступны в Lighthouse), чтобы помочь лучше охватить процесс загрузки после первоначальной отрисовки, но эти метрики сложны, их трудно измерить. объясняют, и часто ошибаются, то есть они до сих пор не определяют, когда загрузился основной контент страницы.
Основываясь на обсуждениях в рабочей группе W3C по веб-производительности и исследованиях, проведенных в Google, мы обнаружили, что более точный способ измерить время загрузки основного содержимого страницы — это посмотреть, когда отображается самый большой элемент.
Что такое ЛКП?
LCP сообщает время рендеринга самого большого изображения или текстового блока , видимого в области просмотра, относительно времени, когда пользователь впервые перешел на страницу.
Что такое хороший показатель LCP?
Чтобы обеспечить хорошее взаимодействие с пользователем, сайты должны стремиться к тому, чтобы наибольшая прорисовка контента составляла 2,5 секунды или меньше. Чтобы гарантировать достижение этой цели для большинства ваших пользователей, хорошим порогом для измерения является 75-й процентиль загрузки страниц, сегментированный по мобильным и настольным устройствам.
Какие элементы учитываются?
Как указано в API Largest Contentful Paint , типы элементов, рассматриваемых для Largest Contentful Paint, следующие:
- Элементы
<img>
( время представления первого кадра используется для анимированного контента, такого как GIF или анимированные PNG) - Элементы
<image>
внутри элемента<svg>
- Элементы
<video>
(используется время загрузки изображения постера или время представления первого кадра видео — в зависимости от того, что наступит раньше) - Элемент с фоновым изображением, загруженным с помощью функции
url()
(в отличие от градиента CSS ). - Элементы уровня блока, содержащие текстовые узлы или другие дочерние текстовые элементы строчного уровня.
Обратите внимание, что ограничение элементов этим ограниченным набором было намеренным, чтобы изначально упростить задачу. Дополнительные элементы (например, полная поддержка <svg>
) могут быть добавлены в будущем по мере проведения дополнительных исследований.
Помимо рассмотрения только некоторых элементов, измерения LCP используют эвристику для исключения определенных элементов, которые пользователи могут счесть «несодержательными». Для браузеров на базе Chromium к ним относятся:
- Элементы с непрозрачностью 0, невидимые для пользователя.
- Элементы, охватывающие всю область просмотра, которые, скорее всего, считаются фоном, а не содержимым.
- Изображения-заполнители или другие изображения с низкой энтропией, которые, вероятно, не отражают истинное содержание страницы.
Браузеры, скорее всего, продолжат совершенствовать эту эвристику, чтобы гарантировать соответствие ожиданиям пользователей относительно самого крупного элемента контента .
Эти «содержательные» эвристики могут отличаться от эвристики, используемой First Contentful Paint (FCP) , которая может учитывать некоторые из этих элементов, такие как изображения-заполнители или изображения полного окна просмотра, даже если они не могут быть кандидатами на LCP. Несмотря на то, что оба используют слово «содержательный» в своем названии, цель этих показателей разная. FCP измеряет, когда какой-либо контент отображается на экране, а LCP — когда отображается основной контент , поэтому LCP должен быть более избирательным.
Как определяется размер элемента?
Размер элемента, сообщаемый для LCP, обычно равен размеру, который виден пользователю в области просмотра. Если элемент выходит за пределы области просмотра, или если какой-либо элемент обрезан или имеет невидимое переполнение , эти части не учитываются при расчете размера элемента.
Для элементов изображения, размер которых был изменен по сравнению с их внутренним размером , сообщается либо видимый размер, либо внутренний размер, в зависимости от того, какой из них меньше.
Для текстовых элементов LCP рассматривает только наименьший прямоугольник, который может содержать все текстовые узлы.
Для всех элементов LCP не учитывает поля, отступы или границы, примененные с помощью CSS.
Когда сообщается о LCP?
Веб-страницы часто загружаются поэтапно, и в результате возможно изменение самого большого элемента на странице.
Чтобы справиться с этой потенциальной возможностью изменения, браузер отправляет PerformanceEntry
типа largest-contentful-paint
идентифицирующий самый большой элемент содержимого, как только браузер нарисовал первый кадр. Но затем, после рендеринга последующих кадров, он будет отправлять еще один PerformanceEntry
каждый раз, когда изменяется самый большой элемент содержимого.
Например, на странице с текстом и главным изображением браузер может первоначально просто отобразить текст, после чего браузер отправит запись largest-contentful-paint
свойство element
которой, скорее всего, будет ссылаться на <p>
или <h1>
. Позже, как только главное изображение завершит загрузку, будет отправлена вторая largest-contentful-paint
, и ее свойство element
будет ссылаться на <img>
.
Элемент может считаться самым большим элементом содержимого только после того, как он отрисован и виден пользователю. Изображения, которые еще не загружены, не считаются «отрисованными». Текстовые узлы также не используют веб-шрифты в период блокировки шрифтов . В таких случаях меньший элемент может быть указан как самый большой элемент с содержимым, но как только больший элемент завершит отрисовку, будет создан другой PerformanceEntry
.
Помимо поздней загрузки изображений и шрифтов, страница может добавлять новые элементы в DOM по мере появления нового контента. Если какой-либо из этих новых элементов больше, чем предыдущий элемент с наибольшим содержимым, также будет сообщено о новом элементе PerformanceEntry
.
Если самый большой элемент с содержимым удаляется из области просмотра или даже из DOM, он остается самым большим элементом с содержимым, пока не будет отображен более крупный элемент.
Браузер перестанет сообщать о новых записях, как только пользователь взаимодействует со страницей (нажатием, прокруткой или нажатием клавиши), поскольку взаимодействие с пользователем часто меняет то, что видит пользователь (что особенно актуально при прокрутке).
В целях анализа вам следует сообщать в свою аналитическую службу только самую последнюю отправленную запись PerformanceEntry
.
Время загрузки и время рендеринга
По соображениям безопасности метка времени рендеринга изображений не отображается для изображений из разных источников, у которых отсутствует заголовок Timing-Allow-Origin
. Вместо этого отображается только время загрузки (поскольку оно уже доступно через многие другие веб-API).
Это может привести к, казалось бы, невозможной ситуации, когда веб-API сообщает о LCP раньше, чем о FCP. Это не так, но так кажется только из-за этого ограничения безопасности.
Если это возможно, всегда рекомендуется устанавливать заголовок Timing-Allow-Origin
, чтобы ваши метрики были более точными.
Как обрабатываются изменения макета и размера элемента?
Чтобы снизить накладные расходы на вычисление и отправку новых записей производительности, изменения размера или положения элемента не создают новых кандидатов LCP. Учитывается только начальный размер и положение элемента в области просмотра.
Это означает, что изображения, которые изначально отображаются за кадром, а затем переходят на экран, могут не сообщаться. Это также означает, что элементы, первоначально отображаемые в области просмотра, а затем вытесняемые вниз, за пределы поля зрения, все равно будут сообщать о своем первоначальном размере в области просмотра.
Примеры
Вот несколько примеров того, когда на нескольких популярных веб-сайтах происходит самая большая содержательная отрисовка:
![Самая большая временная шкала Contentful Paint с сайта cnn.com](https://web.developers.google.cn/static/articles/lcp/image/largest-contentful-paint-fc43128e011aa.png?authuser=5&hl=ru)
![Самая большая временная шкала Contentful Paint от techcrunch.com](https://web.developers.google.cn/static/articles/lcp/image/largest-contentful-paint-3713e2f14970a.png?authuser=5&hl=ru)
На обеих временных шкалах, приведенных выше, самый большой элемент изменяется по мере загрузки контента. В первом примере в DOM добавляется новый контент, в результате чего меняется самый большой элемент. Во втором примере макет изменяется, и содержимое, которое раньше было самым большим, удаляется из области просмотра.
Хотя зачастую контент, загружаемый с опозданием, больше, чем контент, уже находящийся на странице, это не обязательно так. Следующие два примера показывают, что LCP происходит до полной загрузки страницы.
![Самая большая хроника Contentful Paint на instagram.com](https://web.developers.google.cn/static/articles/lcp/image/largest-contentful-paint-9bc403e812154.png?authuser=5&hl=ru)
![Самая большая временная шкала Contentful Paint на сайте google.com](https://web.developers.google.cn/static/articles/lcp/image/largest-contentful-paint-6c5554de0eac7.png?authuser=5&hl=ru)
В первом примере логотип Instagram загружается относительно рано и остается самым крупным элементом, даже несмотря на то, что остальной контент отображается постепенно. В примере страницы результатов поиска Google самым большим элементом является абзац текста, который отображается до завершения загрузки любого изображения или логотипа. Поскольку все отдельные изображения меньше этого абзаца, он остается самым большим элементом на протяжении всего процесса загрузки.
Как измерить ЛКП
LCP можно измерить в лаборатории или в полевых условиях , и он доступен в следующих инструментах:
Полевые инструменты
- Отчет об опыте использования Chrome
- Статистика PageSpeed
- Search Console (отчет «Основные веб-показатели»)
- JavaScript-библиотека
web-vitals
Лабораторные инструменты
Измерение LCP в JavaScript
Чтобы измерить LCP в JavaScript, вы можете использовать Largest Contentful Paint API . В следующем примере показано, как создать PerformanceObserver
, который прослушивает записи largest-contentful-paint
и записывает их в консоль.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
В приведенном выше примере каждая зарегистрированная largest-contentful-paint
представляет текущего кандидата LCP. Обычно значение startTime
последней созданной записи является значением LCP, однако это не всегда так. Не все записи largest-contentful-paint
действительны для измерения LCP.
В следующем разделе перечислены различия между тем, что сообщает API, и тем, как рассчитывается метрика.
Различия между метрикой и API
- API будет отправлять записи
largest-contentful-paint
для страниц, загруженных на фоновую вкладку, но эти страницы следует игнорировать при расчете LCP. - API продолжит отправлять записи
largest-contentful-paint
после того, как страница была переведена в фоновый режим, но эти записи следует игнорировать при вычислении LCP (элементы могут учитываться только в том случае, если страница все время находилась на переднем плане). - API не сообщает о
largest-contentful-paint
когда страница восстанавливается из обратного/прямого кэша , но в этих случаях следует измерять LCP, поскольку пользователи воспринимают их как отдельные посещения страниц. - API не учитывает элементы внутри iframe, но учитывает метрику, поскольку они являются частью взаимодействия пользователя со страницей. На страницах с LCP внутри iframe — например, на постере во встроенном видео — это будет отображаться как разница между CrUX и RUM . Чтобы правильно измерить LCP, вам следует их учитывать. Подкадры могут использовать API для передачи своих записей
largest-contentful-paint
в родительский фрейм для агрегирования. - API измеряет LCP с момента начала навигации, но для предварительно обработанных страниц LCP следует измерять с
activationStart
, поскольку это соответствует времени LCP, ощущаемому пользователем.
Вместо того, чтобы запоминать все эти тонкие различия, разработчики могут использовать библиотеку JavaScript web-vitals
для измерения LCP, которая обрабатывает эти различия за вас (где это возможно — обратите внимание, что проблема с iframe не рассматривается):
import {onLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
onLCP(console.log);
Полный пример измерения LCP в JavaScript можно найти в исходном коде onLCP()
.
Что, если самый большой элемент не является самым важным?
В некоторых случаях наиболее важный элемент (или элементы) на странице не совпадает с самым большим элементом, и вместо этого разработчики могут быть более заинтересованы в измерении времени рендеринга этих других элементов. Это возможно с помощью Element Timing API , как описано в статье о пользовательских метриках .
Как улучшить ЛКП
Доступно полное руководство по оптимизации LCP, которое поможет вам определить сроки LCP в полевых условиях и использовать лабораторные данные для их детализации и оптимизации.
Дополнительные ресурсы
- Уроки, извлеченные из мониторинга производительности в Chrome, автор Энни Салливан на Performance.now() (2019)
Журнал изменений
Иногда ошибки обнаруживаются в API, используемых для измерения метрик, а иногда и в определениях самих метрик. В результате иногда приходится вносить изменения, и эти изменения могут проявляться в виде улучшений или регрессов в ваших внутренних отчетах и информационных панелях.
Чтобы помочь вам справиться с этим, все изменения в реализации или определении этих показателей будут отражены в этом журнале изменений .
Если у вас есть отзывы по этим показателям, вы можете оставить их в группе Google web-vitals-feedback .