Web Vitals предоставляет API для измерения ключевых показателей производительности веб-страницы, таких как Largest Contentful Paint (LCP), Cumulative Layout Shift (CLS) и First Input Delay (FID). В условиях динамически обновляемого контента возникает необходимость аккумулировать дельту изменений метрик, чтобы корректно оценивать качество пользовательского опыта в реальном времени.
Метрики Web Vitals измеряются непрерывно, и их значения могут изменяться по мере загрузки контента или взаимодействия пользователя. Для большинства показателей важно учитывать не абсолютные значения, а изменения относительно предыдущего состояния. Эти изменения принято называть delta.
Пример: CLS рассчитывается как сумма всех смещений элементов на странице. Каждый новый сдвиг добавляется к текущему значению. Прямая передача этих значений в аналитику без агрегации может привести к дублированию и завышению метрики.
Базовый подход к агрегации delta заключается в хранении текущего состояния метрики и накапливании изменений при каждом обновлении. Рассмотрим пример на Jav * aScript:
import {getCLS, getFID, getLCP} from 'web-vitals';
let aggregatedMetrics = {
CLS: 0,
LCP: 0,
FID: 0
};
function aggregateDelta(metric) {
switch(metric.name) {
case 'CLS':
// CLS может приходить с incremental=true, значит значение уже является дельтой
aggregatedMetrics.CLS += metric.value;
break;
case 'LCP':
// Для LCP берем максимальное значение
aggregatedMetrics.LCP = Math.max(aggregatedMetrics.LCP, metric.value);
break;
case 'FID':
// FID измеряется один раз, поэтому берем первое ненулевое значение
if (aggregatedMetrics.FID === 0) {
aggregatedMetrics.FID = metric.value;
}
break;
}
}
getCLS(aggregateDelta);
getLCP(aggregateDelta);
getFID(aggregateDelta);
Ключевые моменты:
Для страниц с ленивой загрузкой или SPA важна корректная агрегация delta, иначе метрики будут искажены. Использование incremental значения CLS позволяет:
Пример обработки incremental CLS:
getCLS((metric) => {
if (metric.delta) {
aggregatedMetrics.CLS += metric.value;
} else {
aggregatedMetrics.CLS = metric.value;
}
});
Здесь metric.delta сигнализирует о том, что значение уже
является приращением относительно предыдущего состояния.
Для аналитики важно не только накапливать метрики, но и срезать их по временным интервалам:
const intervalMetrics = [];
const INTERVAL = 10000; // 10 секунд
setInterval(() => {
intervalMetrics.push({...aggregatedMetrics});
// Можно сбрасывать для новой агрегации в следующем интервале
aggregatedMetrics = {CLS: 0, LCP: 0, FID: 0};
}, INTERVAL);
Такой подход позволяет:
Для SPA и страниц с активным взаимодействием важно учитывать множественные источники метрик:
Пример с учетом событий и вкладок:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
reportMetrics(aggregatedMetrics);
}
});
Метод reportMetrics отправляет накопленные дельты на
сервер аналитики, обеспечивая корректную фиксацию состояния страницы
перед закрытием или сворачиванием вкладки.
При частых обновлениях delta важно минимизировать нагрузку на основной поток:
let clsBuffer = 0;
getCLS((metric) => {
clsBuffer += metric.value;
requestAnimationFrame(() => {
aggregatedMetrics.CLS += clsBuffer;
clsBuffer = 0;
});
});
Такой подход снижает количество операций с DOM и предотвращает избыточное обновление аналитики.
Эти принципы обеспечивают корректное и эффективное накопление показателей Web Vitals при многократных обновлениях страницы и динамическом контенте.