В контексте мониторинга производительности веб-страниц важно
учитывать, что Web Vitals генерирует множество метрик на протяжении
жизненного цикла страницы. В стандартных сценариях одна и та же метрика
может отправляться несколько раз по разным причинам: повторное
вычисление после изменений DOM, события перезагрузки, повторные попытки
измерения при асинхронной загрузке ресурсов. Это приводит к дублированию
данных и искажению аналитики. Для корректного анализа необходимо
реализовать дедупликацию по уникальному идентификатору метрики
(id), который предоставляется каждой метрике Web
Vitals.
Метрики Web Vitals имеют стандартную структуру объекта:
{
name: 'CLS', // Название метрики: LCP, FID, CLS, TTFB
value: 0.05, // Значение метрики
delta: 0.05, // Изменение с момента последней отправки
id: 'v1-12345', // Уникальный идентификатор метрики
entries: [...] // Список PerformanceEntry для конкретной метрики
}
Ключевой элемент для дедупликации — поле
id, оно гарантирует уникальность события на
конкретной сессии страницы.
idНаиболее простым способом является использование объекта
(Map или plain object), где ключом выступает
id метрики. Пример:
import { getCLS, getFID, getLCP } from 'web-vitals';
const sentMetrics = new Map();
function sendMetric(metric) {
if (sentMetrics.has(metric.id)) {
return; // Метрика с таким id уже была отправлена
}
sentMetrics.set(metric.id, true);
// Отправка на сервер или логирование
console.log(metric);
}
getCLS(sendMetric);
getFID(sendMetric);
getLCP(sendMetric);
В этом примере проверка sentMetrics.has(metric.id)
предотвращает повторную обработку одной и той же метрики.
Если метрики собираются в массив перед отправкой, можно применить метод фильтрации:
const metrics = [];
function captureMetric(metric) {
metrics.push(metric);
}
// После сбора всех метрик
const uniqueMetrics = metrics.filter((m, index, self) =>
index === self.findIndex(t => t.id === m.id)
);
uniqueMetrics.forEach(metric => console.log(metric));
Здесь используется проверка findIndex, чтобы оставить
только первую метрику с данным id.
Для сценариев, где важна высокая производительность при большом
количестве метрик, оптимально использовать Set:
const sentIds = new Set();
function handleMetric(metric) {
if (sentIds.has(metric.id)) return;
sentIds.add(metric.id);
// Дальнейшая обработка метрики
console.log(metric);
}
Set обеспечивает O(1) доступ и проверку
уникальности, что критично при высокой частоте метрик, например при
измерении CLS в анимациях.
idid.id.id
метрик до момента их окончательной отправки. Если очистить
sentMetrics слишком рано, произойдет дублирование при
повторных событиях.import { getCLS, getFID, getLCP, getTTFB } from 'web-vitals';
const sentMetricIds = new Set();
function processMetric(metric) {
if (sentMetricIds.has(metric.id)) return;
sentMetricIds.add(metric.id);
const payload = {
metricName: metric.name,
value: metric.value,
delta: metric.delta,
id: metric.id
};
// Отправка на сервер аналитики
fetch('/analytics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
}
getCLS(processMetric);
getFID(processMetric);
getLCP(processMetric);
getTTFB(processMetric);
Данный пример демонстрирует универсальный подход:
независимо от типа метрики, проверка уникальности по id
предотвращает дублирование, а асинхронная отправка гарантирует
сохранение всех данных.
Set вместо объекта для хранения
id при большом количестве метрик.id только на время жизни страницы, чтобы
избежать утечек памяти.Set при переходе между «виртуальными» страницами, если это
необходимо по бизнес-логике.id с батчингом метрик, чтобы уменьшить
количество сетевых запросов.