Дедупликация метрик по полю id

В контексте мониторинга производительности веб-страниц важно учитывать, что Web Vitals генерирует множество метрик на протяжении жизненного цикла страницы. В стандартных сценариях одна и та же метрика может отправляться несколько раз по разным причинам: повторное вычисление после изменений DOM, события перезагрузки, повторные попытки измерения при асинхронной загрузке ресурсов. Это приводит к дублированию данных и искажению аналитики. Для корректного анализа необходимо реализовать дедупликацию по уникальному идентификатору метрики (id), который предоставляется каждой метрике Web Vitals.


Структура метрики Web Vitals

Метрики Web Vitals имеют стандартную структуру объекта:

{
  name: 'CLS',       // Название метрики: LCP, FID, CLS, TTFB
  value: 0.05,       // Значение метрики
  delta: 0.05,       // Изменение с момента последней отправки
  id: 'v1-12345',    // Уникальный идентификатор метрики
  entries: [...]     // Список PerformanceEntry для конкретной метрики
}

Ключевой элемент для дедупликации — поле id, оно гарантирует уникальность события на конкретной сессии страницы.


Основные подходы к дедупликации

1. Использование объекта для хранения уже отправленных 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) предотвращает повторную обработку одной и той же метрики.


2. Дедупликация в реальном времени через фильтры массива

Если метрики собираются в массив перед отправкой, можно применить метод фильтрации:

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.


3. Использование Set для быстрого контроля уникальности

Для сценариев, где важна высокая производительность при большом количестве метрик, оптимально использовать 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 в анимациях.


Важные нюансы работы с id

  1. Идентификаторы уникальны в рамках одной сессии страницы. При перезагрузке страницы или навигации на другой URL новые метрики получат новые id.
  2. Метрики CLS и LCP могут обновляться несколько раз до окончательного значения, но каждый новый объект имеет свой уникальный id.
  3. Для корректной аналитики нужно хранить id метрик до момента их окончательной отправки. Если очистить sentMetrics слишком рано, произойдет дублирование при повторных событиях.
  4. События метрик могут приходить асинхронно из разных колбеков Web Vitals, поэтому дедупликация должна быть глобальной для текущей страницы.

Пример комплексного решения

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 только на время жизни страницы, чтобы избежать утечек памяти.
  • В сценариях с SPA (Single Page Application) необходимо очищать Set при переходе между «виртуальными» страницами, если это необходимо по бизнес-логике.
  • Для аналитики реального времени можно комбинировать дедупликацию по id с батчингом метрик, чтобы уменьшить количество сетевых запросов.