Pamięć podręczna stanu strony internetowej

Data publikacji: 25 maja 2023 r., ostatnia aktualizacja: 25 marca 2025 r.

Pamięć podręczna stanu strony internetowej (bfcache) to rodzaj optymalizacji przeglądarki, która umożliwia błyskawiczną nawigację w obu kierunkach. Znacznie ułatwia użytkownikom przeglądanie stron – zwłaszcza w przypadku wolniejszych sieci i urządzeń.

Jako programiści stron internetowych musimy wiedzieć, jak optymalizować strony pod kątem bfcache, aby użytkownicy mogli korzystać z jej korzyści.

Zgodność z przeglądarką

Wszystkie główne przeglądarki, w tym Chrome od wersji 96, FirefoxSafari, mają pamięć podręczną stanu strony internetowej.

Podstawy pamięci podręcznej stanu strony internetowej

W przypadku pamięci podręcznej stanu strony internetowej zamiast niszczyć stronę, gdy użytkownik z niej wychodzi, odkładamy zniszczenie i wstrzymujemy wykonywanie kodu JavaScript. Jeśli użytkownik szybko wróci, ponownie wyświetlimy stronę i wznowimy wykonywanie kodu JavaScript. Dzięki temu użytkownik może niemal natychmiast przejść do innej strony.

Ile razy zdarzyło Ci się odwiedzić witrynę i kliknąć link, aby przejść do innej strony, a potem zorientować się, że nie o to Ci chodziło, i kliknąć przycisk Wstecz? W takiej sytuacji pamięć podręczna stanu strony internetowej może znacznie przyspieszyć wczytywanie poprzedniej strony:

Bez włączonej pamięci podręcznej stanu strony internetowej Wysyłane jest nowe żądanie wczytania poprzedniej strony. W zależności od tego, jak dobrze strona została zoptymalizowana pod kątem ponownych wizyt, przeglądarka może być zmuszona do ponownego pobrania, przeanalizowania i wykonania niektórych (lub wszystkich) zasobów, które właśnie pobrała.
Z włączoną pamięcią podręczną stanu strony internetowej Wczytanie poprzedniej strony jest praktycznie natychmiastowe, ponieważ całą stronę można przywrócić z pamięci bez konieczności łączenia się z siecią.

Obejrzyj ten film, aby zobaczyć, jak działa pamięć podręczna stanu strony internetowej i jak może przyspieszyć nawigację:

Dzięki bfcache strony wczytują się znacznie szybciej podczas nawigacji do tyłu i do przodu.

W filmie przykład z pamięcią podręczną bfcache jest znacznie szybszy niż przykład bez niej.

Pamięć podręczna bfcache nie tylko przyspiesza nawigację, ale też zmniejsza zużycie danych, ponieważ zasoby nie muszą być pobierane ponownie.

Dane o używaniu Chrome pokazują, że 1 na 10 nawigacji na komputerze i 1 na 5 na urządzeniu mobilnym to nawigacja wstecz lub do przodu. Dzięki włączonej pamięci podręcznej bfcache przeglądarki mogą codziennie eliminować przesyłanie danych i czas ładowania miliardów stron internetowych.

Jak działa „pamięć podręczna”

„Pamięć podręczna” używana przez bfcache różni się od pamięci podręcznej HTTP, która odgrywa własną rolę w przyspieszaniu powrotów na poprzednią stronę. Pamięć podręczna stanu strony internetowej to migawka całej strony w pamięci, w tym sterty JavaScriptu, natomiast pamięć podręczna HTTP zawiera tylko odpowiedzi na wcześniej wysłane żądania. Bardzo rzadko zdarza się, aby wszystkie żądania potrzebne do załadowania strony były realizowane z pamięci podręcznej HTTP, dlatego powtórne wizyty z użyciem przywracania z pamięci podręcznej stanu strony internetowej są zawsze szybsze niż nawet najlepiej zoptymalizowane nawigacje bez użycia tej pamięci.

Zamrożenie strony w celu ewentualnego ponownego włączenia jej w przyszłości jest dość skomplikowane, jeśli chodzi o najlepszy sposób zachowania kodu w trakcie realizacji. Na przykład jak obsługujesz wywołania setTimeout(), w których upłynął limit czasu, gdy strona znajdowała się w pamięci podręcznej typu „wstecz/do przodu”?

Przeglądarki wstrzymują wszystkie oczekujące liczniki czasu i nierozwiązane obietnice na stronach w pamięci podręcznej stanu strony internetowej, w tym niemal wszystkie oczekujące zadania w kolejkach zadań JavaScript, i wznawiają przetwarzanie zadań, jeśli strona zostanie przywrócona z pamięci podręcznej stanu strony internetowej.

W niektórych przypadkach, np. w przypadku czasów oczekiwania i obietnic, ryzyko jest dość niskie, ale w innych może to prowadzić do niejasnego lub nieoczekiwanego działania. Jeśli na przykład przeglądarka wstrzyma zadanie wymagane w ramach transakcji IndexedDB, może to wpłynąć na inne otwarte karty w tej samej domenie, ponieważ do tych samych baz danych IndexedDB może mieć dostęp wiele kart jednocześnie. W rezultacie przeglądarki zwykle nie próbują zapisywać w pamięci podręcznej stron w trakcie transakcji IndexedDB ani podczas korzystania z interfejsów API, które mogą mieć wpływ na inne strony.

Więcej informacji o tym, jak korzystanie z różnych interfejsów API wpływa na możliwość korzystania z pamięci podręcznej stanu strony internetowej, znajdziesz w artykule Optymalizowanie stron pod kątem pamięci podręcznej stanu strony internetowej.

Pamięć podręczna typu „wstecz/do przodu” i elementy iframe

Jeśli strona zawiera osadzone elementy iframe, nie kwalifikują się one oddzielnie do korzystania z pamięci podręcznej stanu strony internetowej. Jeśli na przykład przejdziesz do innego adresu URL w elemencie iframe, poprzednia treść nie zostanie zapisana w pamięci podręcznej, a gdy cofniesz się, przeglądarka „cofnie się” w elemencie iframe, a nie w ramce głównej. Przechodzenie wstecz w elemencie iframe nie będzie jednak korzystać z pamięci podręcznej.

Gdy jednak ramka główna zostanie przywrócona z pamięci podręcznej stanu strony internetowej, osadzone ramki iframe zostaną przywrócone w stanie, w jakim były, gdy strona została zapisana w pamięci podręcznej stanu strony internetowej.

Główna ramka może też zostać zablokowana przed użyciem pamięci podręcznej stanu strony internetowej, jeśli osadzona ramka iframe korzysta z interfejsów API, które to blokują. Aby tego uniknąć, możesz użyć zasad dotyczących uprawnień ustawionych w głównej ramce lub sandboxatrybutów.

Pamięć podręczna „wstecz/dalej” i aplikacje jednostronicowe

Pamięć podręczna typu „wstecz/do przodu” działa w przypadku nawigacji zarządzanej przez przeglądarkę, więc nie działa w przypadku „miękkiej nawigacji” w aplikacji jednostronicowej (SPA). Pamięć podręczna bfcache może jednak pomóc w przypadku powrotu do aplikacji SPA, zamiast ponownego pełnego inicjowania jej od początku.

Interfejsy API do obserwowania pamięci podręcznej stanu strony internetowej

Chociaż bfcache to optymalizacja, którą przeglądarki wykonują automatycznie, deweloperzy powinni wiedzieć, kiedy to się dzieje, aby mogli zoptymalizować pod tym kątem swoje strony i odpowiednio dostosować wszelkie dane lub pomiary wydajności.

Głównymi zdarzeniami używanymi do obserwowania bfcache są zdarzenia przejścia strony pageshowpagehide, które są obsługiwane przez większość przeglądarek.

Nowsze zdarzenia cyklu życia strony – freezeresume – są też wysyłane, gdy strony wchodzą do pamięci podręcznej lub ją opuszczają, a także w innych sytuacjach, np. gdy karta w tle zostaje zamrożona, aby zminimalizować zużycie procesora. Te zdarzenia są obsługiwane tylko w przeglądarkach opartych na Chromium.

Obserwowanie, kiedy strona jest przywracana z pamięci podręcznej

Zdarzenie pageshow jest wywoływane bezpośrednio po zdarzeniu load podczas początkowego wczytywania strony i za każdym razem, gdy strona jest przywracana z pamięci podręcznej „wstecz/dalej”. Zdarzenie pageshow ma właściwość persisted, która przyjmuje wartość true, jeśli strona została przywrócona z pamięci podręcznej stanu strony internetowej, a w przeciwnym razie – false. Właściwość persisted umożliwia odróżnienie zwykłego wczytywania strony od przywracania z pamięci podręcznej stanu strony internetowej. Na przykład:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.');
  } else {
    console.log('This page was loaded normally.');
  }
});

W przeglądarkach obsługujących interfejs Page Lifecycle API zdarzenie resume jest uruchamiane, gdy strony są przywracane z pamięci podręcznej (bezpośrednio przed zdarzeniem pageshow) oraz gdy użytkownik ponownie odwiedza zamrożoną kartę w tle. Jeśli chcesz zaktualizować stan strony po jej zamrożeniu (dotyczy to też stron w bfcache), możesz użyć zdarzenia resume, ale jeśli chcesz zmierzyć współczynnik trafień bfcache w swojej witrynie, musisz użyć zdarzenia pageshow. W niektórych przypadkach może być konieczne użycie obu tych metod.

Szczegółowe informacje o sprawdzonych metodach pomiaru pamięci podręcznej stanu strony internetowej znajdziesz w artykule Jak pamięć podręczna stanu strony internetowej wpływa na pomiary analityczne i skuteczności.

Sprawdzanie, kiedy strona przechodzi do pamięci podręcznej typu „wstecz/do przodu”

Zdarzenie pagehide jest wywoływane, gdy strona jest wyładowywana lub gdy przeglądarka próbuje umieścić ją w pamięci podręcznej typu „wstecz/do przodu”.

Zdarzenie pagehide ma też właściwość persisted. Jeśli jest to false, możesz mieć pewność, że strona nie zostanie wkrótce zapisana w pamięci podręcznej stanu strony internetowej. persistedtrue nie gwarantuje jednak, że strona zostanie zapisana w pamięci podręcznej. Oznacza to, że przeglądarka zamierza zapisać stronę w pamięci podręcznej, ale mogą wystąpić inne czynniki, które to uniemożliwiają.

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('This page *might* be entering the bfcache.');
  } else {
    console.log('This page will unload normally and be discarded.');
  }
});

Podobnie zdarzenie freeze jest wywoływane natychmiast po zdarzeniu pagehide, jeśli wartość persisted to true, ale oznacza to tylko, że przeglądarka zamierza zapisać stronę w pamięci podręcznej. Może jednak odrzucić takie żądanie z kilku powodów, które wyjaśnimy później.

Optymalizacja stron pod kątem pamięci podręcznej stanu strony internetowej

Nie wszystkie strony są przechowywane w pamięci podręcznej stanu strony internetowej, a nawet jeśli tak się stanie, nie pozostaną tam bezterminowo. Aby zmaksymalizować współczynnik trafień w pamięci podręcznej, deweloperzy muszą wiedzieć, co sprawia, że strony kwalifikują się do korzystania z pamięci podręcznej typu „wstecz/do przodu” (i co je z niej wyklucza).

W sekcjach poniżej znajdziesz sprawdzone metody, które zwiększają prawdopodobieństwo, że przeglądarka będzie mogła zapisywać strony w pamięci podręcznej.

Nigdy nie używaj zdarzenia unload

Najważniejszym sposobem optymalizacji pod kątem bfcache we wszystkich przeglądarkach jest nigdy nieużywanie zdarzenia unload. Nigdy!

Zdarzenie unload jest problematyczne dla przeglądarek, ponieważ pojawiło się przed wprowadzeniem pamięci podręcznej typu „wstecz/do przodu”. Wiele stron w internecie działa w oparciu o (rozsądne) założenie, że strona przestanie istnieć po wywołaniu zdarzenia unload. Stanowi to problem, ponieważ wiele z tych stron zostało również utworzonych z założeniem, że zdarzenie unload będzie wywoływane za każdym razem, gdy użytkownik opuści stronę, co nie jest już prawdą (i nie było prawdą od dłuższego czasu).

Przeglądarki stają więc przed dylematem: muszą wybrać między czymś, co może poprawić wygodę użytkowników, ale może też spowodować nieprawidłowe działanie strony.

Na komputerach Chrome i Firefox uznały, że strony, które dodają detektor unload, nie kwalifikują się do korzystania z pamięci podręcznej stanu strony internetowej. Jest to mniej ryzykowne, ale dyskwalifikuje wiele stron. Safari próbuje buforować niektóre strony z detektorem zdarzeń unload, ale aby zmniejszyć ryzyko awarii, nie uruchamia zdarzenia unload, gdy użytkownik opuszcza stronę, co sprawia, że zdarzenie jest bardzo zawodne.

Na urządzeniach mobilnych Chrome i Safari będą próbować zapisywać w pamięci podręcznej strony z detektorem zdarzenia unload, ponieważ ryzyko wystąpienia problemów jest mniejsze ze względu na to, że zdarzenie unload zawsze było bardzo zawodne na urządzeniach mobilnych. Firefox traktuje strony, które używają unload, jako niekwalifikujące się do korzystania z pamięci podręcznej stanu strony internetowej, z wyjątkiem systemu iOS, który wymaga, aby wszystkie przeglądarki korzystały z silnika renderowania WebKit, więc zachowuje się jak Safari.

Zamiast zdarzenia unload używaj zdarzenia pagehide. Zdarzenie pagehide jest aktywowane we wszystkich przypadkach, w których aktywowane jest zdarzenie unload, a także wtedy, gdy strona jest umieszczana w pamięci podręcznej „wstecz/dalej”.

Lighthouse ma no-unload-listeners audyt, który ostrzega deweloperów, jeśli jakikolwiek kod JavaScript na ich stronach (w tym pochodzący z bibliotek innych firm) dodaje unload detektor zdarzeń.

Ze względu na jego zawodność i wpływ na wydajność pamięci podręcznej bfcache Chrome planuje wycofać zdarzenie unload.

Używanie zasady dotyczącej uprawnień, aby uniemożliwić używanie na stronie procedur obsługi wyładowywania

Witryny, które nie używają modułów obsługi zdarzeń unload, mogą zapobiec ich dodawaniu za pomocą zasad dotyczących uprawnień.

Permissions-Policy: unload=()

Zapobiega to również spowalnianiu witryny przez firmy zewnętrzne lub rozszerzenia, które dodają procedury obsługi zwalniania i powodują, że witryna nie kwalifikuje się do korzystania z pamięci podręcznej typu „wstecz/do przodu”.

Dodawaj słuchaczy beforeunload tylko warunkowo

Zdarzenie beforeunload nie powoduje, że strony nie kwalifikują się do pamięci podręcznej stanu strony internetowej w nowoczesnych przeglądarkach, ale wcześniej tak było i nadal jest ono zawodne, więc unikaj jego używania, chyba że jest to absolutnie konieczne.

W odróżnieniu od zdarzenia unload istnieją jednak uzasadnione przypadki użycia zdarzenia beforeunload. Może to być na przykład ostrzeżenie, że użytkownik ma niezapisane zmiany, które utraci, jeśli opuści stronę. W takim przypadku zalecamy dodawanie beforeunload detektorów tylko wtedy, gdy użytkownik ma niezapisane zmiany, a następnie natychmiastowe usuwanie ich po zapisaniu tych zmian.

Nie
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Ten kod dodaje detektor beforeunload bezwarunkowo.
Tak
function beforeUnloadListener(event) {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  window.addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  window.removeEventListener('beforeunload', beforeUnloadListener);
});
Ten kod dodaje detektor beforeunload tylko wtedy, gdy jest potrzebny (i usuwa go, gdy nie jest).

Zminimalizuj użycie Cache-Control: no-store

Cache-Control: no-store to nagłówek HTTP, który serwery WWW mogą ustawiać w odpowiedziach, aby poinstruować przeglądarkę, że nie ma ona przechowywać odpowiedzi w żadnej pamięci podręcznej HTTP. Jest on używany w przypadku zasobów zawierających poufne informacje o użytkownikach, np. stron wymagających logowania.

Pamięć podręczna stanu strony internetowej nie jest pamięcią podręczną HTTP, ale w przeszłości, gdy element Cache-Control: no-store był ustawiony na samym zasobie strony (w przeciwieństwie do dowolnego zasobu podrzędnego), przeglądarki nie przechowywały strony w pamięci podręcznej stanu strony internetowej, więc strony używające Cache-Control: no-store mogą nie kwalifikować się do korzystania z tej pamięci. Pracujemy nad zmianą tego zachowania w Chrome w sposób chroniący prywatność.

Ponieważ Cache-Control: no-store ogranicza możliwość korzystania przez stronę z pamięci podręcznej stanu strony internetowej, należy go ustawiać tylko na stronach zawierających informacje poufne, w przypadku których buforowanie w jakiejkolwiek formie jest niewłaściwe.

W przypadku stron, które muszą zawsze wyświetlać aktualne treści (i nie zawierają informacji poufnych), używaj Cache-Control: no-cache lub Cache-Control: max-age=0. Te dyrektywy nakazują przeglądarce ponowne sprawdzenie treści przed ich udostępnieniem i nie mają wpływu na kwalifikowanie się strony do bfcache.

Pamiętaj, że gdy strona jest przywracana z pamięci podręcznej stanu strony internetowej, jest przywracana z pamięci, a nie z pamięci podręcznej HTTP. W rezultacie dyrektywy takie jak Cache-Control: no-cache czy Cache-Control: max-age=0 nie są brane pod uwagę, a przed wyświetleniem treści użytkownikowi nie następuje ponowna weryfikacja.

Zapewnia to jednak prawdopodobnie większy komfort użytkownikom, ponieważ przywracanie z pamięci podręcznej jest natychmiastowe, a strony nie pozostają w niej zbyt długo, więc jest mało prawdopodobne, że treści są nieaktualne. Jeśli jednak Twoje treści zmieniają się z minuty na minutę, możesz pobrać aktualizacje za pomocą zdarzenia pageshow, jak opisano w następnej sekcji.

Aktualizowanie nieaktualnych lub danych wrażliwych po przywróceniu z pamięci podręcznej

Jeśli Twoja witryna przechowuje stan użytkownika, zwłaszcza poufne informacje o nim, dane te muszą zostać zaktualizowane lub wyczyszczone po przywróceniu strony z pamięci podręcznej typu „wstecz/do przodu”.

Jeśli na przykład użytkownik przejdzie na stronę płatności, a następnie zaktualizuje koszyk na zakupy, przechodzenie wstecz może spowodować wyświetlenie nieaktualnych informacji, jeśli z pamięci podręcznej zostanie przywrócona nieaktualna strona.

Inny, ważniejszy przykład to sytuacja, w której użytkownik wylogowuje się z witryny na komputerze publicznym, a następny użytkownik klika przycisk Wstecz. Może to potencjalnie ujawnić dane prywatne, które użytkownik uznał za usunięte po wylogowaniu.

Aby uniknąć takich sytuacji, zawsze aktualizuj stronę po zdarzeniu pageshow, jeśli event.persisted ma wartość true:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Do any checks and updates to the page
  }
});

Najlepiej byłoby aktualizować treści w miejscu, ale w przypadku niektórych zmian możesz wymusić pełne ponowne wczytanie. Poniższy kod sprawdza obecność pliku cookie w pageshow event i ponownie wczytuje stronę, jeśli plik cookie nie zostanie znaleziony:

window.addEventListener('pageshow', (event) => {
  if (event.persisted && !document.cookie.match(/my-cookie)) {
    // Force a reload if the user has logged out.
    location.reload();
  }
});

Odświeżenie ma tę zaletę, że zachowuje historię (aby umożliwić nawigację do przodu), ale w niektórych przypadkach przekierowanie może być bardziej odpowiednie.

Reklamy i przywracanie z pamięci podręcznej typu „wstecz/do przodu”

Może pojawić się pokusa, aby uniknąć korzystania z bfcache, aby wyświetlać nowy zestaw reklam przy każdej nawigacji do tyłu lub do przodu. Oprócz wpływu na skuteczność reklam takie zachowanie budzi wątpliwości co do tego, czy prowadzi do większego zaangażowania w reklamę. Użytkownicy mogli zauważyć reklamę, którą chcieli kliknąć później, ale po ponownym wczytaniu strony zamiast przywrócenia jej z pamięci podręcznej stanu strony internetowej nie będą mogli tego zrobić. Zanim zaczniesz wyciągać wnioski, warto przetestować ten scenariusz, najlepiej za pomocą testu A/B.

W przypadku witryn, które chcą odświeżać reklamy po przywróceniu z pamięci podręcznej bfcache, odświeżanie tylko reklam w przypadku zdarzenia pageshow, gdy event.persisted ma wartość true, umożliwia to bez wpływu na wydajność strony. Skontaktuj się z dostawcą reklam, ale tutaj znajdziesz przykład, jak to zrobić za pomocą tagu wydawcy Google.

Unikaj odwołań do window.opener

W starszych przeglądarkach, jeśli strona została otwarta za pomocą window.open() z linku z atrybutem target=_blank bez określenia atrybutu rel="noopener", strona otwierająca miała odniesienie do obiektu okna otwartej strony.

Oprócz zagrożenia dla bezpieczeństwa strona z odwołaniem window.opener o wartości innej niż wartość null nie może być bezpiecznie umieszczona w bfcache, ponieważ mogłoby to spowodować nieprawidłowe działanie stron, które próbują uzyskać do niej dostęp.

Dlatego najlepiej unikać tworzenia odwołań window.opener. Możesz to zrobić, używając w miarę możliwości protokołu rel="noopener" (pamiętaj, że jest on teraz domyślnie używany we wszystkich nowoczesnych przeglądarkach). Jeśli Twoja witryna wymaga otwarcia okna i sterowania nim za pomocą window.postMessage() lub bezpośredniego odwoływania się do obiektu okna, ani otwarte okno, ani otwierająca je strona nie będą kwalifikować się do korzystania z pamięci podręcznej.

Zamykanie otwartych połączeń, zanim użytkownik opuści stronę

Jak wspomnieliśmy wcześniej, gdy strona jest przechowywana w pamięci podręcznej typu „wstecz/dalej” (bfcache), wszystkie zaplanowane zadania JavaScript są wstrzymywane i wznawiane, gdy strona jest wyjmowana z pamięci podręcznej.

Jeśli te zaplanowane zadania JavaScriptu mają dostęp tylko do interfejsów DOM API lub innych interfejsów API ograniczonych do bieżącej strony, wstrzymanie ich, gdy strona nie jest widoczna dla użytkownika, nie spowoduje żadnych problemów.

Jeśli jednak te zadania są połączone z interfejsami API, które są też dostępne z innych stron w tej samej domenie (np. IndexedDB, Web Locks, WebSockets), może to być problematyczne, ponieważ wstrzymanie tych zadań może uniemożliwić uruchomienie kodu w innych kartach.

W związku z tym w tych sytuacjach niektóre przeglądarki nie będą próbować umieścić strony w pamięci podręcznej typu „wstecz/do przodu”:

Jeśli Twoja strona korzysta z któregoś z tych interfejsów API, zdecydowanie zalecamy zamykanie połączeń oraz usuwanie lub odłączanie obserwatorów podczas zdarzenia pagehide lub freeze. Dzięki temu przeglądarka może bezpiecznie zapisać stronę w pamięci podręcznej bez ryzyka wpływu na inne otwarte karty.

Jeśli strona zostanie przywrócona z pamięci podręcznej bfcache, możesz ponownie otworzyć lub połączyć się z tymi interfejsami API podczas zdarzenia pageshow lub resume.

Przykład poniżej pokazuje, jak zadbać o to, aby strony korzystające z IndexedDB kwalifikowały się do bfcache, zamykając otwarte połączenie w detektorze zdarzeń pagehide:

let dbPromise;
function openDB() {
  if (!dbPromise) {
    dbPromise = new Promise((resolve, reject) => {
      const req = indexedDB.open('my-db', 1);
      req.onupgradeneeded = () => req.result.createObjectStore('keyval');
      req.onerror = () => reject(req.error);
      req.onsuccess = () => resolve(req.result);
    });
  }
  return dbPromise;
}

// Close the connection to the database when the user leaves.
window.addEventListener('pagehide', () => {
  if (dbPromise) {
    dbPromise.then(db => db.close());
    dbPromise = null;
  }
});

// Open the connection when the page is loaded or restored from bfcache.
window.addEventListener('pageshow', () => openDB());

Sprawdź, czy strony można zapisywać w pamięci podręcznej

Narzędzia deweloperskie w Chrome mogą pomóc Ci przetestować strony, aby upewnić się, że są zoptymalizowane pod kątem bfcache, i wykryć problemy, które mogą uniemożliwiać ich kwalifikację.

Aby przetestować stronę:

  1. Otwórz stronę w Chrome.
  2. W Narzędziach deweloperskich otwórz Aplikacja –> Pamięć podręczna wstecz/dalej.
  3. Kliknij przycisk Uruchom test. Narzędzia deweloperskie próbują następnie przejść do innej strony i wrócić, aby sprawdzić, czy można przywrócić stronę z pamięci podręcznej stanu strony internetowej.
Panel pamięci podręcznej stanu strony internetowej w Narzędziach deweloperskich
Panel Pamięć podręczna stanu strony internetowej w Narzędziach deweloperskich.

Jeśli test się powiedzie, w panelu pojawi się komunikat „Przywrócono z pamięci podręcznej stanu strony internetowej”.

Narzędzia deweloperskie informują, że strona została przywrócona z pamięci podręcznej typu „wstecz/do przodu”
Strona została przywrócona.

Jeśli się nie uda, w panelu pojawi się informacja o przyczynie. Jeśli przyczyna jest czymś, co możesz rozwiązać jako deweloper, panel oznaczy ją jako Wymaga działania.

Narzędzia deweloperskie zgłaszają błąd przywracania strony z pamięci podręcznej stanu strony internetowej
Nieudany test pamięci podręcznej stanu strony internetowej z wynikiem, na który można zareagować.

W tym przykładzie użycie detektora zdarzeń unload sprawia, że strona nie kwalifikuje się do korzystania z pamięci podręcznej stanu strony internetowej. Możesz to naprawić, przechodząc z unload na pagehide:

Tak
window.addEventListener('pagehide', ...);
Nie
window.addEventListener('unload', ...);

W Lighthouse 10.0 dodano też audyt bfcache, który przeprowadza podobny test. Więcej informacji znajdziesz w dokumentacji audytu bfcache.

Jak pamięć podręczna „wstecz/dalej” wpływa na analitykę i pomiar skuteczności

Jeśli używasz narzędzia analitycznego do pomiaru wizyt w witrynie, możesz zauważyć spadek łącznej liczby wyświetleń strony, ponieważ Chrome włącza pamięć podręczną wstecz/do przodu dla większej liczby użytkowników.

Prawdopodobnie już teraz zaniżasz liczbę wyświetleń stron w innych przeglądarkach, które implementują bfcache, ponieważ wiele popularnych bibliotek analitycznych nie rejestruje przywracania z pamięci podręcznej jako nowych wyświetleń stron.

Aby uwzględnić przywracanie z pamięci podręcznej stanu strony internetowej w liczbie wyświetleń strony, ustaw detektory zdarzenia pageshow i sprawdź właściwość persisted.

Poniższy przykład pokazuje, jak to zrobić w Google Analytics. Inne narzędzia analityczne prawdopodobnie używają podobnej logiki:

// Send a pageview when the page is first loaded.
// This happens by default just by loading gtag
gtag('config', 'TAG_ID');

window.addEventListener('pageshow', (event) => {
  // Send another pageview if the page is restored from bfcache.
  if (event.persisted) {
    gtag('event', 'page_view');
  }
});

Mierzenie współczynnika trafień w pamięci podręcznej typu „wstecz/do przodu”

Możesz też mierzyć, czy pamięć podręczna stanu strony internetowej została użyta, aby zidentyfikować strony, które z niej nie korzystają. Możesz to zrobić, mierząc typ nawigacji w przypadku wczytań strony:

// Send a navigation_type when the page is first loaded.
// To do this disable the default pageview so you can manually send it
// supplemented with the additional detail.
gtag('config', 'TAG_ID', { send_page_view: false });
gtag('event', 'page_view', {
   'navigation_type': performance.getEntriesByType('navigation')[0].type;
});

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Send another pageview if the page is restored from bfcache.
    gtag('event', 'page_view', {
      'navigation_type': 'back_forward_cache';
    });
  }
});

Oblicz współczynnik trafień bfcache, korzystając z liczby nawigacji back_forward i nawigacji back_forward_cache.

Pamiętaj, że w wielu sytuacjach, na które właściciel witryny nie ma wpływu, nawigacja Wstecz/Dalej nie będzie korzystać z pamięci podręcznej typu bfcache. Oto niektóre z nich:

  • gdy użytkownik zamknie przeglądarkę i uruchomi ją ponownie.
  • gdy użytkownik duplikuje kartę.
  • gdy użytkownik zamknie kartę i otworzy ją ponownie.

W niektórych przypadkach oryginalny typ nawigacji może być zachowywany przez niektóre przeglądarki, więc może wyświetlać typ back_forward, mimo że nie jest to nawigacja do tyłu ani do przodu.

Nawet bez tych wykluczeń pamięć podręczna bfcache zostanie po pewnym czasie odrzucona, aby oszczędzać pamięć.

Właściciele witryn nie powinni więc oczekiwać 100-procentowego współczynnika trafień bfcache w przypadku wszystkich nawigacji back_forward. Mierzenie tego wskaźnika może jednak pomóc w identyfikowaniu stron, które uniemożliwiają korzystanie z pamięci podręcznej stanu strony internetowej w przypadku dużej części nawigacji do przodu i do tyłu.

Zespół Chrome dodał NotRestoredReasons interfejs API, aby ujawniać przyczyny, dla których strony nie korzystają z pamięci podręcznej wstecz/do przodu. Dzięki temu deweloperzy mogą zwiększać współczynnik trafień w pamięci podręcznej wstecz/do przodu. Zespół Chrome dodał też do CrUX typy nawigacji, dzięki czemu można sprawdzić liczbę nawigacji z pamięci podręcznej stanu strony internetowej bez konieczności samodzielnego pomiaru.

Pomiar skuteczności

Pamięć podręczna może też negatywnie wpływać na dane o wydajności zbierane w terenie, zwłaszcza na dane, które mierzą czas wczytywania strony.

Nawigacja z użyciem pamięci podręcznej stanu strony internetowej przywraca istniejącą stronę, a nie inicjuje nowego wczytywania strony, więc po włączeniu tej funkcji łączna liczba wczytań strony będzie mniejsza. Kluczowe jest jednak to, że wczytania stron zastępowane przez przywracanie z pamięci podręcznej typu „wstecz/do przodu” byłyby prawdopodobnie jednymi z najszybszych wczytań stron w Twoim zbiorze danych. Dzieje się tak, ponieważ nawigacja do tyłu i do przodu z definicji jest powtórną wizytą, a powtórne wczytywanie strony jest zwykle szybsze niż wczytywanie strony przez nowych użytkowników (ze względu na buforowanie HTTP, o którym wspomnieliśmy wcześniej).

W rezultacie w zbiorze danych będzie mniej szybkich wczytań stron, co prawdopodobnie spowoduje przesunięcie rozkładu w stronę wolniejszych wczytań, mimo że wydajność odczuwana przez użytkownika prawdopodobnie się poprawiła.

Ten problem można rozwiązać na kilka sposobów. Pierwszy sposób polega na dodaniu do wszystkich danych o wczytywaniu strony odpowiedniego typu nawigacji: navigate, reload, back_forward lub prerender. Dzięki temu możesz nadal monitorować skuteczność w przypadku tych typów nawigacji, nawet jeśli ogólny rozkład jest ujemny. Zalecamy to podejście w przypadku danych o wczytywaniu strony, które nie są związane z użytkownikami, np. czasu do pierwszego bajtu (TTFB).

W przypadku wskaźników dotyczących użytkowników, takich jak Core Web Vitals, lepszym rozwiązaniem jest podawanie wartości, która dokładniej odzwierciedla wrażenia użytkownika.

Wpływ na Core Web Vitals

Core Web Vitals mierzą wygodę użytkownika podczas korzystania ze strony internetowej w różnych wymiarach (szybkość wczytywania, interaktywność, stabilność wizualna). Przywracanie z pamięci podręcznej stanu strony internetowej jest dla użytkowników szybsze niż pełne wczytywanie strony, dlatego ważne jest, aby odzwierciedlały to dane Core Web Vitals. Użytkownik nie dba o to, czy pamięć podręczna typu „wstecz/do przodu” jest włączona. Zależy mu tylko na tym, aby nawigacja była szybka.

Narzędzia, które zbierają dane o Core Web Vitals i generują na ich podstawie raporty, np. Raport na temat użytkowania Chrome, traktują przywracanie z bfcache jako osobne wizyty na stronie w swoim zbiorze danych. Nie ma dedykowanych interfejsów API do pomiaru tych danych po przywróceniu z pamięci podręcznej stanu strony internetowej, ale możesz przybliżyć ich wartości za pomocą istniejących interfejsów API:

  • W przypadku największego wyrenderowania treści (LCP) użyj różnicy między sygnaturą czasową zdarzenia pageshow a sygnaturą czasową następnej wyrenderowanej ramki, ponieważ wszystkie elementy w ramce zostaną wyrenderowane w tym samym czasie. W przypadku przywracania z pamięci podręcznej stanu strony internetowej LCP i FCP są takie same.
  • W przypadku interakcji do kolejnego wyrenderowania (INP) nadal używaj dotychczasowego obserwatora wydajności, ale zresetuj bieżącą wartość INP do 0.
  • W przypadku skumulowanego przesunięcia układu (CLS) nadal używaj dotychczasowego interfejsu Performance Observer, ale zresetuj bieżącą wartość CLS do 0.

Więcej informacji o tym, jak pamięć podręczna typu „wstecz/do przodu” wpływa na poszczególne wskaźniki, znajdziesz w przewodnikach po poszczególnych wskaźnikach Core Web Vitals. Konkretny przykład wdrażania wersji tych wskaźników z pamięci podręcznej możesz znaleźć w żądaniu dodania ich do biblioteki JS Web Vitals.

Biblioteka JavaScript web-vitals obsługuje przywracanie z pamięci podręcznej bfcache w raportowanych przez siebie danych.

Dodatkowe materiały