Back/forward cache и метрики при bfcache-навигации

Браузеры применяют back/forward cache (bfcache) для ускорения навигации между страницами, сохраняя полное состояние документа в памяти. В отличие от обычного кэширования, bfcache сохраняет DOM, JavaScript-окружение и все ресурсы страницы, что позволяет моментально возвращаться к предыдущей странице без повторной загрузки и рендеринга. Это влияет на измерение Web Vitals, поскольку метрики, рассчитанные при первой загрузке, могут не отражать поведение страницы при возврате из bfcache.


Особенности работы bfcache

  1. Сохранение состояния страницы При переходе на другую страницу текущий документ помещается в bfcache. В этот момент:

    • JavaScript-таймеры останавливаются.
    • DOM и CSSOM остаются в памяти.
    • События visibilitychange и pagehide вызываются перед помещением страницы в bfcache.
  2. Восстановление страницы При возвращении:

    • Страница активируется мгновенно без повторного запроса ресурсов.
    • Срабатывают события pageshow и visibilitychange.
    • Переинициализация JavaScript не происходит, что важно учитывать при расчете метрик.
  3. Отличие от обычной загрузки Метрики типа Largest Contentful Paint (LCP) или Cumulative Layout Shift (CLS), которые отслеживаются в Web Vitals, могут быть некорректными, если не учитывать восстановление из bfcache. Например, LCP рассчитывается только при первой загрузке страницы, а повторный показ страницы не инициирует новое измерение LCP по умолчанию.


Влияние bfcache на ключевые Web Vitals

Largest Contentful Paint (LCP)

  • LCP отражает время появления основного контента страницы.
  • При навигации из bfcache LCP не пересчитывается, так как браузер не инициирует повторный рендер.
  • Чтобы отслеживать LCP при возвращении, можно использовать PerformanceObserver с событием largest-contentful-paint и проверять event.persisted в событии pageshow.
window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('Страница восстановлена из bfcache');
  }
});

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('LCP:', entry.startTime);
  }
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });

First Input Delay (FID)

  • FID измеряет задержку реакции страницы на первый пользовательский ввод.
  • Поскольку скрипты на странице остаются в том же состоянии при восстановлении из bfcache, новый FID обычно не генерируется.
  • Решение: использовать Event Timing API для измерения задержек пользовательских действий после восстановления страницы.
window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('События пользовательского ввода могут быть измерены отдельно');
  }
});

Cumulative Layout Shift (CLS)

  • CLS отслеживает нестабильность макета.
  • Если страница возвращается из bfcache и не происходят новые изменения DOM, CLS не изменяется.
  • Для страниц с динамическим контентом следует использовать session-based CLS, накапливая сдвиги и при восстановлении учитывать их повторно.
let clsValue = 0;
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    clsValue += entry.value;
  }
});
observer.observe({ type: 'layout-shift', buffered: true });

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('CLS на восстановленной странице:', clsValue);
  }
});

Рекомендации по работе с Web Vitals и bfcache

  1. Отслеживание событий pageshow и pagehide

    • pageshow с event.persisted === true сигнализирует о восстановлении страницы.
    • Можно инициировать повторные наблюдения за метриками или корректировать существующие значения.
  2. Буферизация PerformanceObserver

    • Использовать { buffered: true } для LCP и CLS, чтобы получать метрики даже после восстановления страницы.
  3. Session-based подход

    • Для динамических страниц накапливать значения CLS и пользовательские задержки через сессию, чтобы результаты были корректными при возврате из bfcache.
  4. Валидация данных Web Vitals

    • Проверять, что метрики не искажены событиями bfcache.
    • Фильтровать или корректировать данные в аналитических системах для точного измерения UX.

Заключение по технической интеграции

  • bfcache ускоряет навигацию, но требует дополнительного контроля за Web Vitals.
  • Метрики, зависящие от рендеринга (LCP, CLS) и взаимодействия пользователя (FID), должны быть адаптированы для сценариев восстановления страницы.
  • Использование событий pageshow, pagehide и PerformanceObserver обеспечивает корректное отслеживание и накопление метрик при bfcache-навигации.

Эта практика критична для аналитики и оптимизации производительности, особенно для SPA и сайтов с высокой динамикой контента.