Узнайте, как сопоставить данные о производительности с отладочной информацией, чтобы помочь вам выявлять и устранять проблемы реальных пользователей с помощью аналитики.
Google предоставляет две категории инструментов для измерения и отладки производительности:
- Лабораторные инструменты: такие инструменты, как Lighthouse, где ваша страница загружается в смоделированную среду, которая может имитировать различные условия (например, медленную сеть и низкопроизводительное мобильное устройство).
- Полевые инструменты: такие инструменты, как отчет об опыте пользователей Chrome (CrUX), который основан на совокупных данных реальных пользователей Chrome. (Обратите внимание, что данные полей, предоставляемые такими инструментами, как PageSpeed Insights и Search Console , получены из данных CrUX.)
Хотя полевые инструменты предоставляют более точные данные — данные, которые на самом деле отражают то, что испытывают реальные пользователи, — лабораторные инструменты часто лучше помогают выявлять и устранять проблемы.
Данные CrUX более репрезентативны для реальной производительности вашей страницы, но знание ваших оценок CrUX вряд ли поможет вам понять , как улучшить свою производительность.
Lighthouse, с другой стороны, выявит проблемы и внесет конкретные предложения по улучшению. Однако Lighthouse будет предлагать только решения проблем с производительностью, которые он обнаружит во время загрузки страницы. Он не обнаруживает проблемы, которые проявляются только в результате взаимодействия с пользователем, например прокрутки или нажатия кнопок на странице.
В связи с этим возникает важный вопрос: как можно получить отладочную информацию для Core Web Vitals или других показателей производительности от реальных пользователей на местах?
В этом посте подробно объясняется, какие API-интерфейсы вы можете использовать для сбора дополнительной отладочной информации для каждой из текущих метрик Core Web Vitals, а также даются идеи о том, как собирать эти данные в существующем инструменте аналитики.
API для атрибуции и отладки
ЦЛС
Из всех показателей Core Web Vitals CLS , пожалуй, является тем, для которого сбор отладочной информации на местах является наиболее важным. CLS измеряется на протяжении всего жизненного цикла страницы, поэтому то, как пользователь взаимодействует со страницей (как далеко он прокручивает, что нажимает и т. д.), может оказать существенное влияние на то, происходят ли изменения макета и какие элементы смещаются. .
Рассмотрим следующий отчет PageSpeed Insights:
Значения CLS, полученные из лаборатории (Lighthouse), по сравнению с CLS, полученными в полевых условиях (данные CrUX), совершенно разные, и это имеет смысл, если учесть, что на странице может быть много интерактивного контента, который не используется при тестировании. в Маяке.
Но даже если вы понимаете, что взаимодействие с пользователем влияет на данные полей, вам все равно необходимо знать, какие элементы на странице смещаются, чтобы получить оценку 0,3 в 75-м процентиле.
Интерфейс LayoutShiftAttribution делает это возможным.
Получить атрибуцию изменения макета
Интерфейс LayoutShiftAttribution отображается в каждой записи layout-shift
, которую создает API Layout Instability .
Подробное объяснение обоих этих интерфейсов см. в разделе Сдвиги макета отладки . Для целей этой статьи главное, что вам нужно знать, это то, что как разработчик вы можете наблюдать за каждым изменением макета, происходящим на странице, а также за тем, какие элементы смещаются.
Вот пример кода, который регистрирует каждое изменение макета, а также элементы, которые сместились:
new PerformanceObserver((list) => {
for (const {value, startTime, sources} of list.getEntries()) {
// Log the shift amount and other entry info.
console.log('Layout shift:', {value, startTime});
if (sources) {
for (const {node, curRect, prevRect} of sources) {
// Log the elements that shifted.
console.log(' Shift source:', node, {curRect, prevRect});
}
}
}
}).observe({type: 'layout-shift', buffered: true});
Вероятно, непрактично измерять и отправлять данные в ваш аналитический инструмент для каждого произошедшего изменения макета; однако, отслеживая все смены, вы можете отслеживать худшие смены и просто сообщать информацию о них.
Целью не является выявление и исправление каждого отдельного изменения макета, которое происходит у каждого пользователя; Цель состоит в том, чтобы определить изменения, которые затрагивают наибольшее количество пользователей и, таким образом, вносят наибольший вклад в CLS вашей страницы на 75-м процентиле.
Кроме того, вам не нужно вычислять самый большой исходный элемент каждый раз, когда происходит сдвиг, вам нужно делать это только тогда, когда вы готовы отправить значение CLS в свой аналитический инструмент.
Следующий код берет список записей layout-shift
, которые внесли свой вклад в CLS, и возвращает самый большой исходный элемент из самого большого сдвига:
function getCLSDebugTarget(entries) {
const largestEntry = entries.reduce((a, b) => {
return a && a.value > b.value ? a : b;
});
if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
const largestSource = largestEntry.sources.reduce((a, b) => {
return a.node && a.previousRect.width * a.previousRect.height >
b.previousRect.width * b.previousRect.height ? a : b;
});
if (largestSource) {
return largestSource.node;
}
}
}
После того как вы определили самый крупный элемент, способствующий наибольшему сдвигу, вы можете сообщить об этом в свой аналитический инструмент.
Элемент, вносящий наибольший вклад в CLS для конкретной страницы, скорее всего, будет варьироваться от пользователя к пользователю, но если вы объедините эти элементы по всем пользователям, вы сможете создать список изменяющихся элементов, влияющих на наибольшее количество пользователей.
После того как вы определили и устранили основную причину изменений для этих элементов, ваш аналитический код начнет сообщать о небольших изменениях как о «худших» изменениях для ваших страниц. В конце концов, все зарегистрированные изменения будут достаточно малы, чтобы ваши страницы находились в пределах «хорошего» порога 0,1 !
Некоторые другие метаданные, которые может быть полезно захватить вместе с самым большим исходным элементом сдвига:
- Время наибольшего сдвига
- Путь URL-адреса на момент наибольшего сдвига (для сайтов, которые динамически обновляют URL-адрес, например одностраничных приложений).
ЛКП
Для отладки LCP в полевых условиях основная информация, которая вам нужна, — это то, какой конкретный элемент был самым большим элементом (элементом-кандидатом LCP) для этой конкретной загрузки страницы.
Обратите внимание, что вполне возможно (на самом деле это довольно часто), что элемент-кандидат LCP будет отличаться от пользователя к пользователю, даже для одной и той же страницы.
Это может произойти по нескольким причинам:
- Пользовательские устройства имеют разное разрешение экрана, что приводит к разным макетам страниц и, следовательно, к разным элементам, видимым в области просмотра.
- Пользователи не всегда загружают страницы, прокрученные до самого верха. Часто ссылки содержат идентификаторы фрагментов или даже текстовые фрагменты , что означает, что ваши страницы могут загружаться и отображаться в любой позиции прокрутки на странице.
- Содержимое может быть персонализировано для текущего пользователя, поэтому элемент-кандидат LCP может сильно различаться от пользователя к пользователю.
Это означает, что вы не можете делать предположения о том, какой элемент или набор элементов будет наиболее распространенным элементом-кандидатом LCP для конкретной страницы. Вы должны измерять это на основе поведения реальных пользователей.
Определите элемент-кандидат LCP
Чтобы определить элемент-кандидат LCP в JavaScript, вы можете использовать API Largest Contentful Paint — тот же API, который вы используете для определения значения времени LCP.
Наблюдая за записями largest-contentful-paint
, вы можете определить текущий элемент-кандидат LCP, просматривая свойство element
последней записи:
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});
Как только вы узнаете элемент-кандидат LCP, вы можете отправить его в свой аналитический инструмент вместе со значением метрики. Как и в случае с CLS, это поможет вам определить, какие элементы наиболее важно оптимизировать в первую очередь.
В дополнение к элементу-кандидату LCP также может быть полезно измерить время подчасти LCP , что может быть полезно при определении того, какие конкретные шаги оптимизации актуальны для вашего сайта.
ПИД
Для отладки FID в полевых условиях важно помнить, что FID измеряет только часть общей задержки первого входного события. Это означает, что то, с чем взаимодействовал пользователь, на самом деле не так важно, как то, что еще происходило в основном потоке в момент взаимодействия.
Например, многие приложения JavaScript, поддерживающие рендеринг на стороне сервера (SSR), доставляют статический HTML-код, который можно отобразить на экране до того, как он станет интерактивным для пользовательского ввода, то есть до того, как JavaScript, необходимый для интерактивности контента, завершит загрузку.
Для таких типов применений может быть очень важно знать, произошел ли первый ввод до или после гидратации . Если окажется, что многие люди пытаются взаимодействовать со страницей до завершения гидратации, рассмотрите возможность отображения ваших страниц в отключенном или загружаемом состоянии, а не в состоянии, которое выглядит интерактивным.
Если платформа вашего приложения предоставляет временную метку гидратации, вы можете сравнить ее с меткой времени first-input
записи, чтобы определить, произошел ли первый ввод до или после гидратации. Если ваша платформа не предоставляет эту временную метку или вообще не использует гидратацию, еще одним полезным сигналом может быть то, произошел ли ввод до или после завершения загрузки JavaScript.
Событие DOMContentLoaded
возникает после полной загрузки и анализа HTML-кода страницы, что включает в себя ожидание загрузки любых синхронных, отложенных или модульных сценариев (включая все статически импортированные модули). Таким образом, вы можете использовать время этого события и сравнить его с моментом, когда произошел FID.
Следующий код отслеживает записи first-input
и регистрирует, произошел ли первый ввод до окончания события DOMContentLoaded
:
new PerformanceObserver((list) => {
const fidEntry = list.getEntries()[0];
const navEntry = performance.getEntriesByType('navigation')[0];
const wasFIDBeforeDCL =
fidEntry.startTime < navEntry.domContentLoadedEventStart;
console.log('FID occurred before DOMContentLoaded:', wasFIDBeforeDCL);
}).observe({type: 'first-input', buffered: true});
Определите целевой элемент FID и тип события.
Дополнительные потенциально полезные сигналы отладки — это элемент, с которым взаимодействовали, а также тип взаимодействия (например, mousedown
, keydown
, pointerdown
). Хотя взаимодействие с элементом само по себе не влияет на FID (помните, что FID — это всего лишь часть задержки в общей задержке события), знание того, с какими элементами взаимодействуют ваши пользователи, может быть полезно при определении того, как лучше всего улучшить FID.
Например, если подавляющее большинство первых взаимодействий вашего пользователя происходит с определенным элементом, рассмотрите возможность встраивания кода JavaScript, необходимого для этого элемента, в HTML и отложенной загрузки остального.
Чтобы получить тип взаимодействия и элемент, связанный с первым событием ввода, вы можете сослаться на свойства target
и name
first-input
записи:
new PerformanceObserver((list) => {
const fidEntry = list.getEntries()[0];
console.log('FID target element:', fidEntry.target);
console.log('FID interaction type:', fidEntry.name);
}).observe({type: 'first-input', buffered: true});
ИЯФ
INP очень похож на FID в том, что наиболее полезной информацией для сбора в полевых условиях являются:
- С каким элементом взаимодействовал
- Почему это был тип взаимодействия
- Когда произошло это взаимодействие
Как и в случае с FID, основной причиной медленного взаимодействия является блокировка основного потока, которая может быть распространена во время загрузки JavaScript. Знание того, происходят ли наиболее медленные взаимодействия во время загрузки страницы, помогает определить, что необходимо сделать для устранения проблемы.
В отличие от FID, метрика INP учитывает полную задержку взаимодействия, включая время, необходимое для запуска любых зарегистрированных прослушивателей событий, а также время, необходимое для рисования следующего кадра после запуска всех прослушивателей событий. Это означает, что для INP еще полезнее знать, какие целевые элементы обычно приводят к медленному взаимодействию и какие это типы взаимодействий.
Поскольку INP и FID основаны на API синхронизации событий, способ определения этой информации в JavaScript очень похож на предыдущий пример. Следующий код регистрирует целевой элемент и время (относительно DOMContentLoaded
) записи INP.
function logINPDebugInfo(inpEntry) {
console.log('INP target element:', inpEntry.target);
console.log('INP interaction type:', inpEntry.name);
const navEntry = performance.getEntriesByType('navigation')[0];
const wasINPBeforeDCL =
inpEntry.startTime < navEntry.domContentLoadedEventStart;
console.log('INP occurred before DCL:', wasINPBeforeDCL);
}
Обратите внимание, что этот код не показывает, как определить, какая запись event
является записью INP, поскольку эта логика более сложна. Однако в следующем разделе объясняется, как получить эту информацию с помощью библиотеки JavaScript web-vitals .
Использование с библиотекой JavaScript web-vitals
В разделах выше представлены некоторые общие рекомендации и примеры кода для сбора отладочной информации и включения ее в данные, которые вы отправляете в свой инструмент аналитики.
Начиная с версии 3, библиотека JavaScript web-vitals включает в себя сборку атрибуции , которая отображает всю эту информацию, а также несколько дополнительных сигналов .
В следующем примере кода показано, как можно установить дополнительный параметр события (или настраиваемое измерение ), содержащий строку отладки, которая поможет определить основную причину проблем с производительностью.
import {onCLS, onFID, onINP, onLCP} from 'web-vitals/attribution';
function sendToGoogleAnalytics({name, value, id, attribution}) {
const eventParams = {
metric_value: value,
metric_id: id,
}
switch (name) {
case 'CLS':
eventParams.debug_target = attribution.largestShiftTarget;
break;
case 'LCP':
eventParams.debug_target = attribution.element;
break;
case 'FID':
case 'INP':
eventParams.debug_target = attribution.eventTarget;
break;
}
// Assumes the global `gtag()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/ga4
gtag('event', name, eventParams);
}
onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
Этот код специфичен для Google Analytics, но общая идея должна быть применима и к другим инструментам аналитики.
Этот код также просто показывает, как составлять отчеты по одному сигналу отладки, но может быть полезно иметь возможность собирать и составлять отчеты по нескольким различным сигналам для каждой метрики. Например, для отладки INP вам может потребоваться собрать тип взаимодействия, время, а также элемент, с которым происходит взаимодействие. Сборка атрибуции web-vitals
предоставляет всю эту информацию, как показано в следующем примере:
import {onCLS, onFID, onINP, onLCP} from 'web-vitals/attribution';
function sendToGoogleAnalytics({name, value, id, attribution}) {
const eventParams = {
metric_value: value,
metric_id: id,
}
switch (name) {
case 'INP':
eventParams.debug_target = attribution.eventTarget;
eventParams.debug_type = attribution.eventType;
eventParams.debug_time = attribution.eventTime;
eventParams.debug_load_state = attribution.loadState;
break;
// Additional metric logic...
}
// Assumes the global `gtag()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/ga4
gtag('event', name, eventParams);
}
onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
Полный список предоставляемых сигналов отладки см. в документации по атрибуции веб-виталов .
Составляйте отчеты и визуализируйте данные
После того как вы начали собирать отладочную информацию вместе со значениями показателей, следующим шагом будет агрегирование данных обо всех ваших пользователях, чтобы начать поиск закономерностей и тенденций.
Как упоминалось выше, вам не обязательно решать каждую отдельную проблему, с которой сталкиваются ваши пользователи, вы хотите решить (особенно поначалу) проблемы, которые затрагивают наибольшее количество пользователей, которые также должны быть проблемами, которые имеют наибольшее количество проблем. негативное влияние на ваши показатели Core Web Vitals.
Для GA4 см. специальную статью о том , как запрашивать и визуализировать данные с помощью BigQuery .
Краткое содержание
Надеемся, что эта статья помогла обозначить конкретные способы использования существующих API производительности и библиотеки web-vitals
для получения отладочной информации, которая поможет диагностировать производительность на основе посещений реальных пользователей на местах. Хотя это руководство сосредоточено на основных веб-показателях, эти концепции также применимы к отладке любых показателей производительности, которые можно измерить с помощью JavaScript.
Если вы только начинаете измерять производительность и уже являетесь пользователем Google Analytics, инструмент Web Vitals Report может быть хорошим местом для начала, поскольку он уже поддерживает отчеты об отладке для показателей Core Web Vitals.
Если вы являетесь поставщиком аналитических услуг и хотите улучшить свои продукты и предоставить пользователям больше информации для отладки, рассмотрите некоторые из описанных здесь методов, но не ограничивайте себя только идеями, представленными здесь. Этот пост предназначен для общего применения ко всем инструментам аналитики; однако отдельные инструменты аналитики, вероятно, могут (и должны) собирать и сообщать еще больше отладочной информации.
Наконец, если вы чувствуете, что у вас есть пробелы в отладке этих показателей из-за отсутствия функций или информации в самих API, отправьте свой отзыв по адресу web-vitals-feedback@googlegroups.com .