Pamięć podręczna stanu strony internetowej

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 deweloperzy stron internetowych musimy wiedzieć, jak optymalizować strony pod kątem pamięci podręcznej typu „wstecz/do przodu”, aby użytkownicy mogli korzystać z jej zalet.

Zgodność z przeglądarką

Wszystkie główne przeglądarki, w tym Chrome od wersji 96, FirefoxSafari, mają pamięć podręczną wstecz/do przodu.

Podstawowe informacje o bfcache

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 typu „wstecz/do przodu” nie tylko przyspiesza nawigację, ale też zmniejsza zużycie danych, ponieważ zasoby nie muszą być pobierane ponownie.

Dane dotyczące korzystania z 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 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, aby później ponownie ją włączyć, jest dość skomplikowane, jeśli chodzi o najlepszy sposób zachowania kodu w trakcie wykonywania. Na przykład jak obsługujesz setTimeout() połączenia, w których upłynął limit czasu, gdy strona znajdowała się w pamięci podręcznej przeglądarki?

Odpowiedź jest taka, że przeglądarki wstrzymują wszystkie oczekujące timery lub nierozwiązane obietnice na stronach w pamięci podręcznej, w tym prawie wszystkie oczekujące zadania w kolejkach zadań JavaScript, i wznawiają przetwarzanie zadań, jeśli strona zostanie przywrócona z pamięci podręcznej.

W niektórych przypadkach, np. w przypadku limitów czasu 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 będą próbować 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 ze stanu strony w pamięci podręcznej, znajdziesz w artykule Optymalizowanie stron pod kątem pamięci podręcznej stanu strony.

Pamięć podręczna bfcache 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 wrócisz, przeglądarka „cofnie się” w elemencie iframe, a nie w ramce głównej. Cofanie 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 używa 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 bfcache 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 bfcache

Chociaż pamięć podręczna „wstecz/dalej” jest optymalizacją, 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 pomiary danych lub wydajności.

Głównymi zdarzeniami używanymi do obserwowania pamięci podręcznej typu „wstecz/do przodu” 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 typu „wstecz/do przodu”

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 stanu strony internetowej. Zdarzenie pageshow ma właściwość persisted, która przyjmuje wartość true, jeśli strona została przywrócona z pamięci podręcznej przeglądarki, 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 pamięci podręcznej przeglądarki), możesz użyć zdarzenia resume. Jeśli jednak chcesz zmierzyć współczynnik trafień w pamięci podręcznej przeglądarki, 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.

Obserwowanie, kiedy strona wchodzi 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ć zgłoszenie z kilku powodów, które wyjaśnimy później.

Optymalizacja stron pod kątem pamięci podręcznej typu „wstecz/do przodu”

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 pamięci podręcznej typu „wstecz/do przodu” 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ż zbudowanych 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.

W przypadku komputerów Chrome i Firefox zdecydowały, że strony, które dodają odbiornik unload, nie kwalifikują się do bfcache. Jest to mniej ryzykowne, ale dyskwalifikuje wiele stron. Safari próbuje buforować niektóre strony z elementem nasłuchującym zdarzenia 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 elementem nasłuchującym 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 odbiornik zdarzeń unload.

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

Zapobieganie używaniu na stronie procedur obsługi zamykania za pomocą zasady uprawnień

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 sprawiają, że witryna nie kwalifikuje się do korzystania z pamięci podręcznej typu „wstecz/do przodu”.

Dodawaj tylko beforeunload słuchaczy 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 bezwarunkowo odbiornik beforeunload.
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 odbiornik 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 internetowe mogą ustawiać w odpowiedziach, aby poinformować 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 wartość Cache-Control: no-store była ustawiona w zasobie strony (a nie w żadnym zasobie podrzędnym), 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 zapewniający ochronę prywatności.

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 tagów Cache-Control: no-cache lub Cache-Control: max-age=0. Te dyrektywy nakazują przeglądarce ponowne sprawdzenie treści przed ich wyświetleniem i nie mają wpływu na to, czy strona kwalifikuje się do korzystania z pamięci podręcznej przeglądarki.

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 wrażliwych danych 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.

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

Inny, ważniejszy przykład: 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 specyficznego dla witryny w zdarzeniu pageshow 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 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 się wydawać, że warto unikać korzystania z pamięci podręcznej przeglądarki, aby wyświetlać nowy zestaw reklam przy każdej nawigacji do tyłu lub do przodu. Oprócz wpływu na skuteczność takie zachowanie budzi wątpliwości co do tego, czy prowadzi do większego zaangażowania w reklamy. 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 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 typu „wstecz/do przodu”, 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ć w przypadku tagu wydawcy Google.

Unikaj odniesień 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ż null nie może być bezpiecznie umieszczona w pamięci podręcznej przeglądarki, ponieważ mogłoby to spowodować uszkodzenie 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 rel="noopener" (pamiętaj, że jest to teraz domyślne ustawienie 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 stanu strony internetowej, 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 odizolowanych do bieżącej strony, wstrzymanie tych zadań, 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:

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, 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 odbiorniku 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());

Sprawdzanie, 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 pamięci podręcznej typu „wstecz/do przodu”, i wykryć problemy, które mogą uniemożliwiać ich kwalifikowanie się.

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.
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 dodaliśmy też audyt pamięci podręcznej przeglądarki, który przeprowadza podobny test. Więcej informacji znajdziesz w dokumentacji audytu pamięci podręcznej.

Jak pamięć podręczna typu „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 odsłon, 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ą pamięć podręczną wstecz/do przodu, ponieważ wiele popularnych bibliotek analitycznych nie rejestruje przywracania z pamięci podręcznej wstecz/do przodu jako nowych wyświetleń stron.

Aby uwzględnić przywracanie z pamięci podręcznej przeglądarki w liczbie wyświetleń strony, ustaw odbiorniki 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.
gtag('event', 'page_view');

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.
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ń w pamięci podręcznej typu „wstecz/do przodu”, korzystając z liczby nawigacji back_forward i nawigacji back_forward_cache.

Warto pamiętać, że istnieje wiele scenariuszy, na które właściciele witryn nie mają wpływu, w których nawigacja Wstecz/Dalej nie będzie korzystać z pamięci podręcznej typu „wstecz/dalej”. Należą do nich m.in.:

  • 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 z tych przypadków niektóre przeglądarki mogą zachować pierwotny typ nawigacji, więc może się 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ń 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, dzięki czemu deweloperzy mogą zwiększać odsetek trafień w pamięci podręcznej. Zespół Chrome dodał też do CrUX typy nawigacji, dzięki czemu można sprawdzić liczbę nawigacji z pamięci podręcznej 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.

Ponieważ nawigacja z użyciem pamięci podręcznej stanu strony internetowej przywraca istniejącą stronę, a nie inicjuje nowego wczytywania strony, po włączeniu tej funkcji łączna liczba zebranych wczytań strony zmniejszy się. 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 przodu i do tyłu to z definicji powtórne wizyty, a powtórne wczytywanie stron jest zwykle szybsze niż wczytywanie stron przez osoby odwiedzające je po raz pierwszy (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żytkownikiem, np. czasu do pierwszego bajtu (TTFB).

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

Wpływ na podstawowe wskaźniki internetowe

Podstawowe wskaźniki internetowe mierzą wygodę użytkownika podczas korzystania ze strony internetowej w różnych aspektach (szybkość wczytywania, interaktywność, stabilność wizualna). Przywracanie z pamięci podręcznej jest dla użytkowników szybsze niż pełne wczytywanie strony, dlatego ważne jest, aby odzwierciedlały to dane Podstawowych wskaźników internetowych. Użytkownikowi nie zależy na tym, czy pamięć podręczna stanu strony internetowej jest włączona, tylko na tym, aby nawigacja była szybka.

Narzędzia, które zbierają dane o podstawowych wskaźnikach internetowych i generują na ich podstawie raporty, np. Raport na temat użytkowania Chrome, traktują przywracanie z pamięci podręcznej stanu strony internetowej jako oddzielne 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, 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 klatki, ponieważ wszystkie elementy w klatce zostaną wyrenderowane w tym samym czasie. W przypadku przywracania z pamięci podręcznej 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 dane, znajdziesz na stronach przewodników dotyczących poszczególnych wskaźników Core Web Vitals. Konkretny przykład wdrażania wersji tych danych w pamięci podręcznej znajdziesz w żądaniu dodania ich do biblioteki JavaScript web-vitals.

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

Dodatkowe materiały