Отправка в собственный бэкенд

Библиотека Web Vitals предоставляет возможность измерять ключевые показатели производительности веб-страницы в реальном времени. Для передачи этих метрик на собственный сервер необходимо правильно организовать сбор данных, их упаковку и отправку с минимальным влиянием на производительность.


Подключение библиотеки

Для работы с Web Vitals необходимо установить официальный пакет:

npm install web-vitals

или подключить его через CDN:

<script src="https://unpkg.com/web-vitals"></script>

В браузере библиотека предоставляет глобальный объект webVitals, а в Node.js/ESM используется импорт:

import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals';

Основные метрики и их структура

Web Vitals измеряет следующие показатели:

  • CLS (Cumulative Layout Shift) — суммарное смещение элементов страницы.
  • FID (First Input Delay) — задержка при первом взаимодействии пользователя с элементами.
  • LCP (Largest Contentful Paint) — время отображения самого крупного видимого элемента.
  • FCP (First Contentful Paint) — время от начала загрузки страницы до появления первого контента.
  • TTFB (Time to First Byte) — время ответа сервера до получения первого байта.

Каждая метрика передается как объект с ключевыми свойствами:

{
  name: 'LCP',        // название метрики
  value: 2345.67,     // численное значение в миллисекундах
  id: 'v1-12345',     // уникальный идентификатор замера
  delta: 0,           // разница с предыдущим значением (для CLS)
  entries: [...]      // подробные записи PerformanceEntry
}

Функция отправки данных на сервер

Для безопасной и эффективной передачи данных на бэкенд рекомендуется использовать navigator.sendBeacon, если поддерживается браузером. Этот метод отправляет данные асинхронно, не блокируя закрытие страницы.

function sendToBackend(metric) {
  const url = '/api/web-vitals';
  const body = JSON.stringify({
    name: metric.name,
    value: metric.value,
    id: metric.id,
    delta: metric.delta,
    entries: metric.entries
  });

  if (navigator.sendBeacon) {
    const blob = new Blob([body], { type: 'application/json' });
    navigator.sendBeacon(url, blob);
  } else {
    fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body
    }).catch(console.error);
  }
}

Особенности метода sendBeacon:

  • Не блокирует закрытие страницы.
  • Ограничен в размере отправляемых данных (обычно до 64 кБ).
  • Отправка происходит в фоновом потоке, что снижает влияние на производительность.

Регистрация метрик для отправки

Для каждой метрики нужно вызвать соответствующую функцию Web Vitals, передав коллбэк для отправки на сервер:

import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals';

getCLS(sendToBackend);
getFID(sendToBackend);
getLCP(sendToBackend);
getFCP(sendToBackend);
getTTFB(sendToBackend);

Метрики будут передаваться на сервер по мере их измерения, включая те, которые обновляются динамически (например, CLS).


Оптимизация передачи данных

  1. Агрегация перед отправкой Если требуется минимизировать количество запросов, можно накапливать метрики в массив и отправлять их пакетами каждые N секунд:

    const metricsQueue = [];
    
    function enqueueMetric(metric) {
      metricsQueue.push(metric);
      if (metricsQueue.length >= 5) {
        flushMetrics();
      }
    }
    
    function flushMetrics() {
      sendToBackend({ metrics: metricsQueue.splice(0) });
    }
    
    getCLS(enqueueMetric);
    getFID(enqueueMetric);
    getLCP(enqueueMetric);
  2. Дебаунс и таймаут Для событий, которые обновляются часто, используется задержка перед отправкой последней версии метрики:

    let lcpTimeout;
    getLCP(metric => {
      clearTimeout(lcpTimeout);
      lcpTimeout = setTimeout(() => sendToBackend(metric), 1000);
    });
  3. Минимизация объема данных Не обязательно отправлять весь массив entries. Для бэкенда часто достаточно value, name и id.


Настройка бэкенда

На серверной стороне необходимо принимать POST-запросы с JSON-данными:

// Пример на Node.js с Express
app.post('/api/web-vitals', express.json(), (req, res) => {
  const metrics = req.body.metrics ? req.body.metrics : [req.body];
  
  metrics.forEach(metric => {
    // Сохранение в базу данных или аналитическую систему
    console.log(metric.name, metric.value);
  });

  res.status(200).end();
});

Советы по серверной обработке:

  • Логировать только ключевые поля метрики.
  • Использовать асинхронную запись в базу данных.
  • Фильтровать дублирующиеся метрики для улучшения точности аналитики.

Передача контекстной информации

Для полезной аналитики вместе с метриками рекомендуется отправлять дополнительную информацию:

  • URL страницы (window.location.href)
  • User-Agent
  • Идентификатор сессии или пользователя

Пример формирования payload:

function sendToBackend(metric) {
  const payload = {
    metric,
    page: window.location.href,
    userAgent: navigator.userAgent,
    sessionId: window.sessionStorage.getItem('sessionId')
  };

  const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' });
  navigator.sendBeacon('/api/web-vitals', blob);
}

Отслеживание производительности без задержек

Использование sendBeacon и агрегации позволяет получать данные в реальном времени без заметного влияния на работу страницы. Это особенно важно для метрик, таких как FID и CLS, которые фиксируются в момент взаимодействия пользователя или во время динамических изменений контента.


Эта методика обеспечивает надежный сбор и передачу метрик Web Vitals на собственный бэкенд с минимальной нагрузкой на производительность и максимальной точностью данных.