Pamięć podręczna stanu strony internetowej

Pamięć podręczna stanu strony internetowej (bfcache) to optymalizacja przeglądarki, która umożliwia błyskawiczną nawigację do przodu i do tyłu. Znacznie poprawia komfort przeglądania internetu, zwłaszcza u użytkowników korzystających z wolniejszych sieci lub urządzeń.

Programiści stron internetowych muszą wiedzieć, jak zoptymalizować swoje strony pod kątem pamięci podręcznej stanu strony internetowej, aby użytkownicy mogli z nich korzystać.

Zgodność z przeglądarką

Jest ona obsługiwana od wielu lat w Firefoksie i Safari, zarówno na komputerach, jak i na urządzeniach mobilnych.

Począwszy od wersji 86 Chrome włączył tę funkcję w przypadku niewielkiego odsetka użytkowników podczas nawigacji w różnych witrynach na Androidzie. W kolejnych wersjach stopniowo wprowadzamy dodatkową obsługę. Od wersji 96 pamięć podręczna jest włączona dla wszystkich użytkowników Chrome korzystających z komputerów i urządzeń mobilnych.

Podstawowe informacje o pamięci podręcznej stanu strony internetowej

bfcache to działająca w pamięci podręcznej, która zawiera pełną migawkę strony (wraz ze stertą JavaScriptu), gdy użytkownik ją opuszcza. Gdy w pamięci znajduje się cała strona, przeglądarka może ją szybko przywrócić, jeśli użytkownik zechce do niej wrócić.

Ile razy zdarzyło Ci się odwiedzić witrynę i kliknąć link, aby przejść na inną stronę, ale potem okazywało się, że strona nie była tym, czego oczekujesz, i naciśnij przycisk Wstecz? W takim przypadku pamięć podręczna może mieć duży wpływ na szybkość wczytywania poprzedniej strony:

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

Obejrzyj ten film o pamięci podręcznej stanu strony internetowej, aby dowiedzieć się, jak ta funkcja może przyspieszyć nawigację:

Korzystanie z pamięci podręcznej stanu strony internetowej znacznie przyspiesza wczytywanie stron podczas nawigacji wstecz i do przodu.

W filmie przykład z pamięci podręcznej stanu strony internetowej jest znacznie szybszy niż przykład bez niego.

bfcache nie tylko przyspiesza nawigację, ale też zmniejsza użycie danych, bo nie trzeba ponownie pobierać zasobów.

Dane o korzystaniu z Chrome wskazują, że 1 na 10 nawigacji na komputerze i 1 na 5 na urządzeniach mobilnych korzysta z nawigacji wstecz lub do przodu. Przy włączonej pamięci podręcznej przeglądarki przeglądarki mogą wyeliminować przenoszenie danych i czas poświęcany na wczytywanie miliardów stron internetowych każdego dnia.

Jak działa pamięć podręczna

„Pamięć podręczna” wykorzystywana przez bfcache różni się od pamięci podręcznej HTTP, która odgrywa własną rolę w przyspieszaniu powtarzania nawigacji. Bfcache to zrzut całej strony w pamięci, w tym sterty JavaScriptu, podczas gdy pamięć podręczna HTTP zawiera tylko odpowiedzi na wcześniej wysłane żądania. W przypadku żądań z pamięci podręcznej HTTP bardzo rzadko zdarza się, by wczytano stronę, więc powtórne wizyty z użyciem przywracania bfcache są zawsze szybsze niż nawet najlepiej zoptymalizowane nawigację bez pamięci podręcznej.

Tworzenie zrzutu strony w pamięci wymaga jednak pewnej złożoności, jeśli chodzi o możliwość jak najlepszego zachowania kodu w toku. Na przykład, jak obsługiwać wywołania setTimeout(), gdy limit czasu został przekroczony, gdy strona znajduje się w pamięci podręcznej stanu strony internetowej?

Odpowiedź brzmi: przeglądarki wstrzymują wszystkie oczekujące liczniki czasu lub nierozstrzygnięte obietnice dotyczące stron w pamięci podręcznej stanu strony internetowej (w tym prawie wszystkie oczekujące zadania w kolejkach zadań JavaScript) i wznawiają zadania przetwarzania, gdy strona zostanie przywrócona z pamięci podręcznej stanu strony internetowej.

W niektórych przypadkach, na przykład w przypadku przekroczenia limitu czasu i obietnic, jest to dość niewielkie ryzyko, ale w innych może prowadzić do niejasnego lub nieoczekiwanego działania. Jeśli na przykład przeglądarka wstrzyma zadanie, które jest wymagane w ramach transakcji IndexedDB, może to mieć wpływ na inne otwarte karty w tym samym źródle, ponieważ do tych samych baz danych IndexedDB można uzyskać dostęp jednocześnie za pomocą wielu kart. W rezultacie przeglądarki zwykle nie próbują zapisywać stron w pamięci podręcznej 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 różne sposoby wykorzystywania interfejsu API wpływają na kwalifikowanie się stron do buforowania stron w pamięci podręcznej stanu strony internetowej, znajdziesz w artykule Optymalizacja stron pod kątem pamięci podręcznej (bfcache).

BFcache i elementy iframe

Jeśli strona zawiera osadzone elementy iframe, same elementy iframe nie są odpowiednie do korzystania z pamięci podręcznej stanu strony internetowej. Jeśli na przykład przejdziesz do innej strony w elemencie iframe, a potem wrócisz do poprzedniej strony, przeglądarka cofnie się do elementu iframe, a nie do ramki głównej. Przejście wsteczne w elemencie iframe nie będzie korzystać z pamięci podręcznej stanu strony internetowej.

Ramka głównej może też zablokować użycie pamięci podręcznej stanu strony internetowej, jeśli osadzony element iframe używa interfejsów API, które to blokują. Aby tego uniknąć, można użyć zasady uprawnień ustawionej w ramce głównej lub atrybutów sandbox.

Pamięć podręczna i aplikacje na jednej stronie (SPA)

Ponieważ bufor bfcache działa w nawigowaniu zarządzanym przez przeglądarkę, nie działa w przypadku „pozornej nawigacji” w aplikacji jednostronicowej (SPA). Użycie pamięci podręcznej jest jednak nadal przydatne, gdy wrócisz do SPA, zamiast ponownie zainicjować aplikację od początku.

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

Chociaż buforowanie bfcache to optymalizacja wykonywana automatycznie przez przeglądarki, deweloperzy powinni wiedzieć, kiedy się dzieje, aby mogli zoptymalizować swoje strony pod kątem tej funkcji i odpowiednio dostosować wszelkie dane i pomiar wydajności.

Głównymi zdarzeniami służącymi do obserwowania pamięci podręcznej są zdarzenia przejścia na stronę pageshow i pagehide, które są obsługiwane przez większość przeglądarek.

Nowsze zdarzenia Cykl życia stronyfreeze i resume – są też wysyłane, gdy strony otwierają lub opuszczają pamięć podręczną, a także w innych sytuacjach, np. gdy karta w tle zostaje zablokowana, aby zminimalizować wykorzystanie procesora. Te zdarzenia są obsługiwane tylko w przeglądarkach opartych na Chromium.

Obserwuj, kiedy strona zostaje przywrócona z pamięci podręcznej stanu strony internetowej

Zdarzenie pageshow jest uruchamiane zaraz po zdarzeniu load podczas początkowego wczytywania strony i za każdym razem, gdy strona jest przywrócona z pamięci podręcznej stanu strony internetowej. Zdarzenie pageshow ma właściwość persisted, czyli true, jeśli strona została przywrócona z bfcache lub false w przeciwnym razie. Możesz użyć właściwości persisted, aby odróżnić zwykłe wczytywanie stron od przywracania 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, które obsługują interfejs Page Lifecycle API, zdarzenie resume jest wywoływane, gdy strony są przywracane z pamięci podręcznej stanu strony internetowej (bezpośrednio przed zdarzeniem pageshow) i gdy użytkownik ponownie otworzy zablokowaną kartę w tle. Jeśli chcesz zaktualizować stan strony po jej zablokowaniu (w tym stron w pamięci podręcznej stanu strony internetowej), możesz użyć zdarzenia resume, ale jeśli chcesz mierzyć częstotliwość trafień dotyczących pamięci podręcznej witryny, musisz użyć zdarzenia pageshow. W niektórych przypadkach konieczne może być użycie obu.

Szczegółowe informacje o sprawdzonych metodach dotyczących pomiarów pamięci podręcznej stanu strony internetowej znajdziesz w artykule Jak bfcache wpływa na statystyki i pomiar skuteczności.

Obserwuj, kiedy strona wchodzi do pamięci podręcznej stanu strony internetowej

Zdarzenie pagehide jest wywoływane przy wyładowywaniu strony lub gdy przeglądarka próbuje umieścić ją w pamięci podręcznej stanu strony internetowej.

Zdarzenie pagehide ma też właściwość persisted. Jeśli jest to false, możesz mieć pewność, że ta strona nie zostanie umieszczona w pamięci podręcznej stanu strony internetowej. Jednak ustawienie persisted true nie gwarantuje, że strona będzie przechowywana w pamięci podręcznej. Oznacza to, że przeglądarka intends buforować stronę, ale mogą istnieć inne czynniki, które uniemożliwiają jej zapisanie.

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 uruchamia się bezpośrednio po zdarzeniu pagehide, jeśli persisted ma wartość true, ale oznacza to tylko, że przeglądarka intends zapisywanie strony w pamięci podręcznej. Z różnych powodów, które wyjaśnimy w dalszej części prezentacji, konieczne może być jej odrzucenie.

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

Nie wszystkie strony są przechowywane w pamięci podręcznej stanu strony internetowej. Nawet jeśli strona zostanie tam zapisana, nie będzie przechowywana w pamięci podręcznej. Deweloperzy muszą wiedzieć, co sprawia, że strony kwalifikują się do korzystania z pamięci podręcznej stanu strony internetowej (i nie kwalifikują się), aby zmaksymalizować współczynnik trafień w pamięci podręcznej.

W poniższych sekcjach opisano sprawdzone metody, które pozwalają maksymalnie zwiększyć prawdopodobieństwo, że przeglądarka zapisze strony w pamięci podręcznej.

Nigdy nie używaj zdarzenia unload

Najważniejszym sposobem optymalizacji pod kątem pamięci podręcznej we wszystkich przeglądarkach jest nieużywanie zdarzenia unload. Nigdy!

Zdarzenie unload jest problematyczne dla przeglądarek, ponieważ wychodzi naprzeciw pamięci podręcznej stanu strony internetowej, a wiele stron w internecie działa na podstawie (rozsądnego) założeniu, że strona nie istnieje po uruchomieniu zdarzenia unload. Stanowi to wyzwanie, ponieważ w wielu z tych stron założono również, że zdarzenie unload będzie uruchamiać się przy każdym odwołaniu użytkownika, co jest już niezgodne z prawdą (i od dawna to nie było możliwe).

Przeglądarki stoją przed dylematem, więc muszą wybrać coś, co poprawi wygodę użytkowników, ale może też ryzykować zepsucie strony.

Chrome i przeglądarka Chrome na komputerach zdecydowały, że strony nie kwalifikują się do korzystania z pamięci podręcznej stanu strony internetowej, jeśli dodają detektor unload, co jest mniej ryzykowne, ale jednocześnie zdyskwalifikuje wiele stron. Safari spróbuje zapisać w pamięci podręcznej niektóre strony za pomocą detektora zdarzeń unload, ale w celu zmniejszenia potencjalnych problemów nie będzie uruchamiać zdarzenia unload, gdy użytkownik opuści stronę, co sprawi, że zdarzenie będzie bardzo zawodne.

Na urządzeniach mobilnych Chrome i Safari będą próbować zapisywać w pamięci podręcznej strony z detektorem zdarzeń unload, ponieważ ryzyko uszkodzenia jest mniejsze, ponieważ zdarzenie unload zawsze było bardzo zawodne na urządzeniach mobilnych. Przeglądarka Firefox traktuje strony, które używają unload, jako niekwalifikujące się do korzystania z pamięci podręcznej stanu strony internetowej. Nie dotyczy to systemu iOS, który wymaga, aby wszystkie przeglądarki korzystały z mechanizmu renderowania WebKit, dlatego działają one jak Safari.

Zamiast zdarzenia unload używaj zdarzenia pagehide. Zdarzenie pagehide jest uruchamiane we wszystkich przypadkach, w których działa zdarzenie unload, oraz również, gdy strona zostanie umieszczona w pamięci podręcznej stanu strony internetowej.

Lighthouse przeprowadza kontrolę no-unload-listeners, która ostrzega deweloperów, jeśli kod JavaScript na ich stronach (w tym ten z bibliotek zewnętrznych) doda detektor zdarzeń unload.

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

Aby zapobiec używaniu na stronie modułów obsługi unload, użyj zasad dotyczących uprawnień

Witryny, które nie korzystają z modułów obsługi zdarzeń unload, mogą mieć pewność, że nie będą one dodawane za pomocą zasad dotyczących uprawnień z Chrome 115.

Permission-Policy: unload()

Zapobiega to też spowalnianiu działania strony przez inne firmy i rozszerzenia, dodając moduły obsługi unload, co wykluczy stronę z pamięci podręcznej stanu strony internetowej.

Dodaj tylko beforeunload detektorów warunkowo

Zdarzenie beforeunload nie sprawi, że Twoje strony będą kwalifikować się do korzystania z pamięci podręcznej stanu strony internetowej w nowoczesnych przeglądarkach, ale wcześniej tak się stało i nadal jest on zawodny, więc nie używaj go, o ile nie jest to absolutnie konieczne.

W przeciwieństwie do zdarzenia unload istnieją jednak możliwe przypadki użycia właściwości beforeunload. Jeśli na przykład chcesz ostrzec użytkownika, że wprowadził niezapisane zmiany, to utraci, jeśli opuści stronę. W takiej sytuacji zalecamy, aby dodawać detektory beforeunload tylko wtedy, gdy użytkownik ma niezapisane zmiany, a następnie usunąć je natychmiast po zapisaniu niezapisanych zmian.

Nie wolno
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Ten kod bezwarunkowo dodaje 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 jest potrzebny).

Minimalizowanie użycia funkcji Cache-Control: no-store

Cache-Control: no-store to nagłówek HTTP, który można ustawić na odpowiedzi informujące przeglądarkę, że ma nie zapisywać odpowiedzi w żadnej pamięci podręcznej HTTP. Jest używany w przypadku zasobów zawierających poufne dane użytkownika, np. stron wymagających logowania.

Chociaż pamięć podręczna HTTP nie jest pamięcią podręczną HTTP, to dotychczas, gdy atrybut Cache-Control: no-store był ustawiony w samym zasobie strony (w przeciwieństwie do dowolnego zasobu podrzędnego), przeglądarki zdecydowały, że nie będą zapisywać strony w pamięci podręcznej stanu strony internetowej. Pracujemy nad zmianą tego działania w Chrome, chroniąc prywatność, ale obecnie żadne strony używające atrybutu Cache-Control: no-store nie będą kwalifikować się do korzystania z pamięci podręcznej stanu strony internetowej.

Atrybut Cache-Control: no-store ogranicza uprawnienia strony do korzystania z pamięci podręcznej stanu strony internetowej, dlatego należy go ustawiać tylko na stronach zawierających informacje poufne, w przypadku których buforowanie jakichkolwiek informacji nie jest najlepszym rozwiązaniem.

W przypadku stron, które muszą zawsze wyświetlać aktualne treści, które nie zawierają informacji poufnych, użyj Cache-Control: no-cache lub Cache-Control: max-age=0. Dyrektywy te nakazują przeglądarce ponowną weryfikację treści przed jej wyświetleniem i nie wpływają na zgodność strony z pamięci podręcznej stanu strony internetowej.

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

W dalszym ciągu zapewnia to większą wygodę użytkownikom, ale przywracanie danych z pamięci podręcznej stanu strony internetowej odbywa się natychmiast, a skoro strony nie pozostają w tej pamięci zbyt długo, to mało prawdopodobne, aby treść była nieaktualna. Jeśli jednak treści zmieniają się z minuty na minutę, możesz pobrać aktualizacje za pomocą zdarzenia pageshow, jak opisano w następnej sekcji.

Aktualizuj nieaktualne lub wrażliwe dane po przywróceniu pamięci podręcznej stanu strony internetowej

Jeśli Twoja witryna zachowuje stan użytkownika, a zwłaszcza wszelkie poufne informacje o nim, po przywróceniu strony z pamięci podręcznej stanu strony internetowej trzeba je zaktualizować lub wyczyścić.

Jeśli na przykład użytkownik przejdzie na stronę płatności, a potem zaktualizuje koszyk na zakupy, wsteczna nawigacja może spowodować wyświetlenie nieaktualnych informacji po przywróceniu nieaktualnej strony z pamięci podręcznej stanu strony internetowej.

Kolejnym, najważniejszym przykładem jest wylogowanie się z witryny na komputerze publicznym, a następny użytkownik kliknie przycisk Wstecz. Może to spowodować ujawnienie prywatnych danych, które użytkownik przypuszczał, że został wyczyszczony po wylogowaniu.

Aby uniknąć takich sytuacji, warto zawsze aktualizować 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
  }
});

Optymalnym rozwiązaniem jest zaktualizowanie zawartości, ale w przypadku niektórych zmian może być konieczne wymuszenie pełnego ponownego załadowania. Ten kod sprawdza, czy w zdarzeniu pageshow znajduje się plik cookie z konkretnej witryny, a w przypadku braku pliku cookie wczytuje się ponownie:

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

Ponowne załadowanie ma tę zaletę, że pozwala zachować historię (umożliwia przekazywanie do przodu nawigacji), ale w niektórych przypadkach bardziej odpowiednie może się okazać przekierowanie.

Przywracanie reklam i pamięci podręcznej stanu strony internetowej

Może być kuszące, aby uniknąć korzystania z pamięci podręcznej stanu strony internetowej, aby wyświetlać nowy zestaw reklam przy każdej nawigacji wstecz/do przodu. Oprócz wpływu na skuteczność można mieć wątpliwości, czy takie działania zwiększają zaangażowanie użytkowników w reklamę. Użytkownicy mogli zauważyć reklamę, którą chcieli wrócić do kliknięcia, ale nie mogli jej przywrócić, ładując ją ponownie z pamięci podręcznej. Sprawdzenie tego scenariusza, najlepiej za pomocą testu A/B, jest ważne przed przyjęciem założeń.

W przypadku witryn, które chcą odświeżać reklamy przy przywracaniu pamięci podręcznej, a potem odświeżanie tylko reklam w zdarzeniu pageshow, gdy event.persisted ma wartość true, jest to możliwe bez wpływu na wydajność strony. Skontaktuj się z dostawcą reklam. Oto jeden z przykładów, jak to zrobić za pomocą tagu wydawcy Google.

Unikaj odwołań do kategorii window.opener

W starszych przeglądarkach, jeśli strona została otwarta za pomocą window.open() za pomocą linku zawierającego target=_blank, ale bez parametru rel="noopener", strona otwierająca będzie zawierać odwołanie do obiektu window na otwartej stronie.

Strony z odwołaniem o wartości window.opener nie tylko stanowiącą zagrożenie dla bezpieczeństwa, nie można bezpiecznie umieścić w pamięci podręcznej stanu strony internetowej, ponieważ może to uszkodzić strony, które próbują uzyskać do niej dostęp.

Dlatego najlepiej unikać tworzenia plików referencyjnych window.opener. Możesz to zrobić, używając rel="noopener", gdy tylko jest to możliwe (uwaga: teraz jest to ustawienie domyślne we wszystkich nowoczesnych przeglądarkach). Jeśli Twoja witryna wymaga otwarcia okna i sterowania nim za pomocą window.postMessage() lub bezpośredniego odwołania do obiektu window, ani otwarte okno, ani przycisk otwierający nie będą się kwalifikować do pamięci podręcznej stanu strony internetowej.

Zamknij otwarte połączenia, zanim użytkownik opuści stronę

Jak wspomnieliśmy wcześniej, gdy strona zostanie umieszczona w pamięci podręcznej stanu strony internetowej, wstrzymuje ono wszystkie zaplanowane zadania JavaScript i wznowuje je po usunięciu strony z pamięci podręcznej.

Jeśli te zaplanowane zadania JavaScript mają dostęp tylko do interfejsów DOM API lub innych interfejsów API wyodrębnionych tylko z 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 tym samym źródle (np. IndexedDB, Web Locks, WebSockets), może to powodować problemy, ponieważ wstrzymanie tych zadań może uniemożliwić uruchomienie kodu na innych kartach.

Dzięki temu niektóre przeglądarki nie będą próbowały umieścić strony w pamięci podręcznej w tych sytuacjach:

Jeśli Twoja strona korzysta z któregokolwiek z tych interfejsów API, zdecydowanie zalecamy zamknięcie połączeń oraz usunięcie lub rozłączanie obserwatorów podczas zdarzenia pagehide lub freeze. Dzięki temu przeglądarka może bezpiecznie buforować stronę bez ryzyka uszkodzenia innych otwartych kart.

Następnie, jeśli strona zostanie przywrócona z pamięci podręcznej stanu strony internetowej, możesz ponownie otworzyć te interfejsy API lub ponownie się z nimi połączyć podczas zdarzenia pageshow lub resume.

Z przykładu poniżej dowiesz się, jak sprawdzić, czy strony korzystające z IndexedDB kwalifikują się do korzystania z pamięci podręcznej stanu strony internetowej przez zamknięcie otwartego połączenia 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());

Przeprowadź test, aby upewnić się, że strony mogą być zapisywane w pamięci podręcznej

Narzędzia deweloperskie w Chrome pomogą Ci przetestować strony pod kątem optymalizacji pod kątem buforowania w pamięci podręcznej stanu strony internetowej oraz zidentyfikować ewentualne 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 stanu strony internetowej.
  3. Kliknij przycisk Uruchom test. Następnie spróbują wyjść i z powrotem sprawdzić, czy stronę można przywrócić 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 stanu strony internetowej
Strona została przywrócona.

W przypadku niepowodzenia w panelu pojawi się przyczyna. Jeśli przyczyna jest taka, że możesz zająć się nią jako deweloper, w panelu oznaczy ją jako Praktyczne.

Nie udało się przywrócić strony z pamięci podręcznej stanu strony internetowej w Narzędziach deweloperskich
Nieudany test pamięci podręcznej stanu strony internetowej z wynikiem umożliwiającym działanie.

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ć, przełączając się z unload na pagehide:

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

Narzędzie Lighthouse 10.0 dodało też kontrolę pamięci podręcznej (bfcache), która przeprowadza podobny test. Więcej informacji znajdziesz w dokumentacji kontroli bfcache.

Jak bfcache wpływa na statystyki i pomiar skuteczności

Jeśli korzystasz z narzędzia analitycznego do pomiaru wizyt w swojej witrynie, możesz zauważyć spadek łącznej liczby odsłon rejestrowanych przez Chrome, ponieważ Chrome udostępnia pamięć podręczną dla większej liczby użytkowników.

Prawdopodobnie zaniżasz już liczbę wyświetleń stron wywołanych przez inne przeglądarki, które stosują buforowanie bfcache, ponieważ wiele popularnych bibliotek analitycznych nie zlicza nowych odsłon strony bfcache.

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

Poniższy przykład pokazuje, jak to zrobić za pomocą Google Analytics. Inne narzędzia analityczne prawdopodobnie wykorzystują podobną logikę:

// 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');
  }
});

Mierz współczynnik trafień w pamięci podręcznej stanu strony internetowej

Warto też sprawdzić, czy używana była pamięć podręczna stanu strony internetowej, by zidentyfikować strony, które nie korzystają z tej pamięci. Można to zrobić, mierząc typ nawigacji dla wczytywania 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ń dla pamięci podręcznej (bfcache) na podstawie liczników dla nawigacji back_forward i back_forward_cache.

Warto pamiętać, że jest wiele sytuacji, które pozostają poza kontrolą właścicieli witryn, gdy w ramach nawigacji Wstecz/Dalej nie jest używana pamięć podręczna stanu strony internetowej:

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

W niektórych z tych przypadków oryginalny typ nawigacji może zostać zachowany przez niektóre przeglądarki, przez co może być wyświetlany typ back_forward, mimo że nie są to nawigacja wstecz/do przodu.

Nawet bez tych wykluczeń pamięć podręczna jest odrzucana po określonym czasie, aby oszczędzać pamięć.

Właściciele witryn nie powinni więc oczekiwać, że współczynnik trafień dotyczących pamięci podręcznej będzie równy 100% w przypadku wszystkich elementów nawigacyjnych w usłudze back_forward. Jednak pomiar ich współczynnika może być przydatny w identyfikacji stron, na których sama strona uniemożliwia wykorzystanie pamięci podręcznej w przypadku dużej liczby nawigacji wstecz i do przodu.

Zespół Chrome dodał interfejs API NotRestoredReasons, aby pomóc ujawnić powody, dla których strony nie korzystają z pamięci podręcznej stanu strony internetowej. Dzięki temu deweloperzy mogą zwiększyć liczbę trafień tego typu. Zespół Chrome dodał typy nawigacji do raportu CrUX, dzięki czemu można zobaczyć liczbę przekierowań do pamięci podręcznej stanu strony internetowej nawet bez samodzielnego pomiaru.

Pomiar skuteczności

Pamięć podręczna może również negatywnie wpływać na wskaźniki wydajności zbierane w polu, a zwłaszcza dane, które mierzą czas wczytywania strony.

Ponieważ elementy nawigacyjne w pamięci podręcznej stanu strony internetowej przywracają istniejącą stronę, a nie inicjują jej nowe wczytanie, po włączeniu tej pamięci łączna liczba zebranych wczytań stron się zmniejszy. Najważniejsze jest jednak to, że wczytywanie strony przez przywrócenie pamięci podręcznej (bfcache) powinno być jednym z najszybszych wczytywania stron w zbiorze danych. Dzieje się tak, ponieważ nawigacja wstecz i do przodu oznacza z definicji powtarzające się wizyty, a powtórne wczytywanie strony jest zwykle szybsze niż wczytywanie strony przez nowego użytkownika (dzięki buforowaniu przez HTTP, jak już wspomnieliśmy).

W rezultacie w związku z tym, że w zbiorze danych działa mniej szybkich stron wczytywanych, rozkład prawdopodobnie będzie wolniejszy – chociaż prawdopodobnie poprawiła się wydajność.

Istnieje kilka sposobów, które pomogą Ci radzić sobie z tym problemem. Pierwszym z nich jest dodanie adnotacji do wszystkich danych dotyczących wczytywania strony przy użyciu odpowiednich typów nawigacji: navigate, reload, back_forward lub prerender. Pozwala to kontynuować monitorowanie skuteczności w ramach tych typów nawigacji, nawet jeśli ogólne odchylenie rozkładu jest ujemne. Zalecamy tę metodę w przypadku nieukierunkowanych na użytkownika danych o wczytywaniu strony, np. czasu do pierwszego bajtu (TTFB).

W przypadku danych nastawionych na użytkownika, np. podstawowych wskaźników internetowych, lepiej jest zgłosić wartość, która lepiej odzwierciedla wrażenia użytkownika.

Wpływ na podstawowe wskaźniki internetowe

Podstawowe wskaźniki internetowe mierzą wrażenia użytkownika dotyczące strony internetowej w różnych wymiarach (szybkość wczytywania, interaktywność, stabilność wizualna). Ponieważ pamięć podręczna jest przywracana przez użytkowników jako szybsza nawigacja niż ładowanie całej strony, ważne jest, aby to odzwierciedlały w podstawowych wskaźnikach internetowych. W końcu użytkownik nie interesuje się, czy pamięć podręczna jest włączona, ale zależy mu tylko na tym, aby nawigacja była szybka!

Narzędzia, które zbierają dane o podstawowych wskaźnikach internetowych i generują raporty na ich temat, takie jak Raport na temat użytkowania Chrome, traktują przywrócenie pamięci podręcznej stanu strony internetowej jako osobne wizyty stron w swoim zbiorze danych. Chociaż nie istnieją specjalne interfejsy API do pomiaru wydajności w sieci po przywróceniu pamięci podręcznej, możesz oszacować ich wartości za pomocą istniejących internetowych interfejsów API:

  • W przypadku największego wyrenderowania treści (LCP) użyj delta między sygnaturą czasową zdarzenia pageshow a sygnaturą sygnatury czasowej następnej wyrenderowanej klatki, ponieważ wszystkie elementy w klatce zostaną wyrenderowane w tym samym czasie. W przypadku przywrócenia pamięci podręcznej stanu strony internetowej LCP i FCP są takie same.
  • W przypadku interakcji z kolejnym wyrenderowaniem (INP) korzystaj z dotychczasowego obserwatora wydajności, ale zresetuj bieżącą wartość INP do 0.
  • W przypadku funkcji skumulowane przesunięcie układu (CLS) nadal używaj istniejącego obserwatora skuteczności, ale zresetuj obecną wartość CLS na 0.

Więcej informacji o wpływie pamięci podręcznej (bfcache) na poszczególne dane znajdziesz na stronach z przewodnikami dotyczącymi poszczególnych podstawowych wskaźników internetowych. Konkretny przykład implementacji wersji bfcache tych wskaźników znajdziesz w opisie dodawania ich do biblioteki JS web-vitals.

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

Dodatkowe materiały