bfcache (back/forward cache) — это механизм браузера, который позволяет мгновенно восстанавливать состояние страницы при навигации «назад» или «вперед». Страница при этом не перезагружается полностью, а возвращается из кэша вместе со всеми скриптами, DOM и состоянием. Это ускоряет работу и повышает отзывчивость интерфейса, но накладывает особенности на измерения Web Vitals.
Core Web Vitals (LCP, FID, CLS) изначально рассчитаны для обычной загрузки страницы. При использовании bfcache поведение этих метрик меняется:
LCP (Largest Contentful Paint)
pageshow с persisted = true, чтобы определить,
что страница восстановлена из bfcache, и заново инициировать измерение
LCP.FID (First Input Delay)
pointerdown,
keydown и touchstart с учетом
pageshow.persisted.CLS (Cumulative Layout Shift)
LayoutShift после события pageshow.import {getLCP, getFID, getCLS} from 'web-vitals';
function trackVitalsFromBFCache() {
function initWebVitals() {
getLCP(console.log);
getFID(console.log);
getCLS(console.log);
}
// Обработка обычной загрузки
window.addEventListener('load', initWebVitals);
// Обработка возврата из bfcache
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
initWebVitals();
}
});
}
trackVitalsFromBFCache();
Разбор кода:
pageshow, которое срабатывает как
при обычной загрузке, так и при восстановлении из bfcache.persisted указывает на то, что страница была
загружена из кэша, а не с сервера.getLCP, getFID и getCLS
повторно позволяет корректно собирать метрики после восстановления
состояния.DOMContentLoaded, не
срабатывают при восстановлении страницы из bfcache.setTimeout или
requestAnimationFrame, могут оставаться в состоянии
«заморожено», пока страница не будет видима.Пример проверки CLS при восстановлении страницы:
let clsValue = 0;
let clsEntries = [];
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
clsEntries.push(entry);
}
}
});
observer.observe({type: 'layout-shift', buffered: true});
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
console.log('CLS после восстановления из bfcache:', clsValue);
// Очистка для следующего восстановления
clsValue = 0;
clsEntries = [];
}
});
buffered: true при наблюдении за Layout
Shift позволяет захватывать события, которые произошли до подключения
наблюдателя.pageshow.persisted.