Prerendering и метрики при активации пред-рендера

Prerendering позволяет предварительно загружать страницы перед тем, как пользователь действительно на них перейдет. Это снижает время до интерактивности и улучшает воспринимаемую производительность, но также вносит специфические нюансы в измерение Web Vitals. Библиотека Web Vitals в JavaScript предоставляет API для отслеживания ключевых метрик производительности, таких как Largest Contentful Paint (LCP), First Input Delay (FID), Cumulative Layout Shift (CLS) и Interaction to Next Paint (INP), которые необходимо корректно интерпретировать при prerendering.


Работа метрик при prerendering

Когда страница находится в состоянии prerendering:

  • LCP и FID не начинают учитываться до того момента, когда документ станет видимым пользователю. Это предотвращает искажение данных из-за загрузки скрытой страницы.
  • CLS ведет себя аналогично: смещения элементов на невидимой странице не учитываются, пока не произойдет активация.
  • INP, как метрика интерактивности, также игнорирует события на prerendered-документе, так как пользователь ещё не может взаимодействовать с интерфейсом.

Для корректного измерения важно отслеживать событие visibilitychange или использовать свойство document.prerendering (доступно в современных браузерах), чтобы знать момент активации страницы.

if ('prerendering' in document && document.prerendering) {
  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'visible') {
      startWebVitalsTracking();
    }
  });
} else {
  startWebVitalsTracking();
}

Инициализация Web Vitals после активации

Функция startWebVitalsTracking запускает регистрацию метрик через Web Vitals:

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

function startWebVitalsTracking() {
  getCLS(console.log); // или отправка на аналитический сервер
  getFID(console.log);
  getLCP(console.log);
  getINP(console.log);
}

Важный момент: вызов этих функций до того, как страница станет видимой, приведет к отсутствию данных, поскольку все метрики ориентируются на реальные пользовательские события и визуальные изменения.


Практические нюансы измерения LCP

  • LCP фиксируется для самого крупного видимого элемента. На prerendered-странице это значение пусто до активации.
  • Если на странице есть изображения с loading="lazy", LCP может не зафиксироваться сразу, даже после активации. Рекомендуется использовать IntersectionObserver или слушать событие load для ключевых медиа-ресурсов.
  • В случае Single Page Application (SPA) нужно учитывать маршрутизацию. LCP может перезаписываться при навигации между пререндеренными и активными страницами.

Управление CLS при prerendering

Cumulative Layout Shift измеряет неожиданные смещения элементов:

  • На этапе prerendering смещения не влияют на CLS.
  • После активации страницы можно измерять смещения стандартным способом:
getCLS(metric => {
  console.log('CLS:', metric.value);
});
  • Если страницы активно подгружают контент через JavaScript, необходимо учитывать динамическое изменение DOM после активации, чтобы корректно фиксировать метрику.

Метрика FID и INP

FID измеряет задержку первого взаимодействия, INP – качество интерактивности на протяжении сессии:

  • На prerendered-странице FID не фиксируется, так как пользователь не может кликнуть или прокрутить.
  • Для INP важно учитывать, что события взаимодействия начинают собираться только после visibilityState === 'visible'.
  • В SPA-проектах INP лучше отслеживать повторно при каждом переходе между активными маршрутами, чтобы не терять данные о взаимодействиях.

Рекомендации по интеграции

  1. Отложенный старт: запуск Web Vitals только после активации страницы.
  2. Логирование на сервер: отправка метрик после visibilitychange позволяет собирать чистые данные для анализа.
  3. Корректная работа с lazy-ресурсами: LCP и CLS могут зависеть от загрузки изображений и шрифтов, необходимо учитывать их события.
  4. SPA и динамические страницы: перезапуск измерения Web Vitals при изменении маршрута предотвращает потерю данных.

Пример комплексного подхода

function initWebVitals() {
  const startTracking = () => {
    import('web-vitals').then(({ getCLS, getFID, getLCP, getINP }) => {
      getCLS(sendMetric);
      getFID(sendMetric);
      getLCP(sendMetric);
      getINP(sendMetric);
    });
  };

  if ('prerendering' in document && document.prerendering) {
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'visible') {
        startTracking();
      }
    });
  } else {
    startTracking();
  }

  function sendMetric(metric) {
    fetch('/analytics', {
      method: 'POST',
      body: JSON.stringify(metric),
      headers: { 'Content-Type': 'application/json' }
    });
  }
}

initWebVitals();

Такой подход обеспечивает точное измерение метрик Web Vitals для страниц с prerendering, минимизируя искажения данных и позволяя получить достоверные показатели производительности.