Pamięć podręczna stanu strony internetowej

Optymalizuj strony pod kątem szybkiego ładowania podczas korzystania z przycisków Wstecz i Dalej w przeglądarce.

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 dla osób korzystających z wolniejszych sieci lub urządzeń.

Deweloperzy muszą wiedzieć, jak zoptymalizować strony pod kątem pamięci podręcznej stanu strony internetowej we wszystkich przeglądarkach, aby użytkownicy mogli z nich korzystać.

Zgodność z przeglądarką

Usługa bfcache od wielu lat jest obsługiwana zarówno w Firefoksie, jak i w Safari, zarówno na komputerach, jak i na urządzeniach mobilnych.

Począwszy od wersji 86, u niewielkiego odsetka użytkowników Chrome włączał pamięć podręczną przeglądarki na potrzeby 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 pamięć podręczna, 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 i łatwo przywrócić, gdy 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 okazało się, że strona nie była tym, czego oczekujesz, i klikniesz 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 wykonania niektórych (lub wszystkich) właśnie pobranych zasobów.
Z włączoną pamięcią podręczną strony (bfcache) Wczytywanie poprzedniej strony odbywa się zasadniczo natychmiast, ponieważ całą stronę można przywrócić z pamięci bez konieczności łączenia się z siecią.

Obejrzyj ten film na temat pamięci podręcznej stanu strony internetowej, aby dowiedzieć się, jaka jest szybkość usprawniania nawigacji:

W powyższym filmie przykład z żądaniem bfcache jest znacznie szybszy niż bez niej.

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 skrócić czas poświęcany na wczytywanie miliardów stron internetowych każdego dnia.

Jak działa pamięć podręczna

„Pamięć podręczna” używana przez bfcache różni się od pamięci podręcznej HTTP (która jest również przydatna w przypadku szybszej nawigacji). Bfcache to zapis całej strony w pamięci (łącznie ze stertą JavaScriptu), podczas gdy pamięć podręczna HTTP zawiera tylko odpowiedzi na wcześniej zgłoszone żądania. Ponieważ dość rzadko zdarza się, że wszystkie żądania wymagane do wczytania strony mogą zostać zrealizowane z pamięci podręcznej HTTP, powtórne wizyty z użyciem przywracania bfcache są zawsze szybsze niż nawet najlepiej zoptymalizowane nawigację bez pamięci podręcznej.

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

Wynika to z tego, że przeglądarki wstrzymują uruchamianie wszelkich oczekujących liczników czasu lub nierozstrzygniętych zadań – zasadniczo wszystkich oczekujących zadań w kolejkach zadań JavaScript – i wznawiają zadania przetwarzania po przywróceniu strony z pamięci podręcznej stanu strony (lub jeśli).

W niektórych przypadkach jest to niewielkie ryzyko (np. przekroczenie limitu czasu oczekiwania lub obietnice), ale w innych może prowadzić do bardzo 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 na wielu kartach). 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 korzystania z interfejsu API wpływają na kwalifikowanie się stron do pamięci podręcznej stanu strony internetowej, znajdziesz w sekcji Optymalizowanie stron pod kątem buforowania bfcache poniżej.

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

Bfcache działa w przypadku nawigacji zarządzanych przez przeglądarkę. Dlatego nie działa z tak zwanymi „miękkimi nawigacji” w SPA, ale jedną z największych zalet tego typu aplikacji jest to, że i tak powinny one być szybkie. Użycie pamięci podręcznej stanu strony internetowej na pewno przyda się, 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, ważne jest, aby deweloperzy wiedzieli, kiedy się dzieje, aby mogli zoptymalizować strony pod kątem tego celu i odpowiednio dostosować wszelkie wskaźniki lub pomiary wydajności.

Głównymi zdarzeniami służącymi do obserwowania pamięci podręcznej są zdarzenia przenoszenia stron (pageshow i pagehide), które występują od momentu, w którym buforowana jest pamięć podręczna (bfcache) i są obsługiwane w niemal wszystkich dzisiejszych przeglądarkach.

Nowsze zdarzenia Cykl życia stronyfreeze i resume – są też wysyłane, gdy strony trafiają do pamięci podręcznej lub z niej, a także w innych sytuacjach. np. gdy karta w tle zostaje zablokowana, aby zminimalizować wykorzystanie procesora. Zdarzenia cyklu życia strony są obecnie 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, gdy strona wczytuje się po raz pierwszy 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 wynosi true, jeśli strona zostanie przywrócona z pamięci podręcznej stanu strony internetowej (lub false, jeśli nie). Do odróżniania zwykłego wczytywania stron od przywracania pamięci podręcznej stanu strony internetowej możesz używać właściwości persisted. 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 będzie się też uruchamiać, gdy strony zostaną przywrócone z pamięci podręcznej stanu strony internetowej (bezpośrednio przed zdarzeniem pageshow), ale będzie ono również uruchamiane, 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 warto użyć obu.

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

Zdarzenie pagehide to odpowiednik zdarzenia pageshow. Zdarzenie pageshow jest wywoływane, gdy strona wczytuje się normalnie lub jest przywrócona z pamięci podręcznej stanu strony internetowej. Zdarzenie pagehide jest wywoływane, gdy strona zostanie normalnie wyładowana z pamięci 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, a jeśli ma wartość false, możesz mieć pewność, że strona nie trafi do pamięci podręcznej stanu strony internetowej. Jeśli jednak właściwość persisted ma wartość true, nie gwarantuje, że strona będzie przechowywana w pamięci podręcznej. Oznacza to, że przeglądarka intends zapisać stronę w pamięci podręcznej, ale istnieją 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 jest wywoływane bezpośrednio po zdarzeniu pagehide (jeśli jego właściwością persisted jest true), ale ponownie oznacza to, że tylko przeglądarka intends do zapisywania strony w pamięci podręcznej. Mimo to może być konieczne jej odrzucenie z kilku powodów opisanych poniżej.

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

Nie wszystkie strony są zapisywane w pamięci podręcznej stanu strony internetowej. Nawet jeśli strona zostanie tam zapisana, nie będzie istnieć bez końca. 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 sekcjach poniżej przedstawiamy 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 optymalizowania 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. Wiele stron w internecie działa przy założeniu, że strona nie istnieje po uruchomieniu zdarzenia unload. Stanowi to wyzwanie, ponieważ wiele z tych stron zostało również utworzonych przy założeniu, że zdarzenie unload będzie uruchamiane za każdym razem, gdy użytkownik opuścił witrynę, co już jest niezgodne z prawdą (i od dawna tak się nie dzieje).

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

Chrome i Firefox decydują, że strony na komputerach nie kwalifikują się do korzystania z pamięci podręcznej stanu strony internetowej, gdy dodają detektor unload. Jest to 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 spowoduje, ż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 obecnie trwa 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ą zagwarantować, że nie będą one dodawane za pomocą zasad dotyczących uprawnień z Chrome 115.

Permission-Policy: unload()

Zapobiega to spowalnianiu strony przez inne firmy i rozszerzenia przez dodanie modułów unload, co sprawi, że witryna nie będzie kwalifikować się do korzystania 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
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);
});
Powyższy 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. Tej opcji należy używać 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.

Jeśli chcesz, aby strona była zawsze aktualna, a ta strona nie zawiera informacji poufnych, użyj Cache-Control: no-cache lub Cache-Control: max-age=0. Te dyrektywy informują przeglądarkę o konieczności ponownej weryfikacji 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 poufne informacje o nim, po przywróceniu strony z pamięci podręcznej stanu strony internetowej trzeba je zaktualizować lub wyczyścić.

Na przykład: jeśli użytkownik przejdzie na stronę płatności, a potem zaktualizuje koszyk na zakupy, nawigacja wsteczna może potencjalnie ujawnić nieaktualne informacje 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 danych prywatnych, które użytkownik przyjął, że zostały wyczyszczone 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 całkowite ponowne załadowanie strony. 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 unikać korzystania z pamięci podręcznej stanu strony internetowej w celu wyświetlania nowego zestawu reklam w każdej nawigacji wstecz i 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ą zamierzali ponownie kliknąć, ale nie mogli tego zrobić, ładując ponownie stronę z pamięci podręcznej stanu strony internetowej. 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 z linkiem target=_blank (bez określania wartości rel="noopener"), strona otwierająca będzie zawierać odwołanie do obiektu window na otwartej stronie.

Oprócz zagrożenia dla bezpieczeństwa strony z wartością inną niż zero window.opener nie można bezpiecznie umieścić w pamięci podręcznej, ponieważ mogłoby to spowodować uszkodzenie stron, które usiłują uzyskać do niej dostęp.

Dlatego najlepiej unikać tworzenia plików referencyjnych window.opener. Gdy tylko jest to możliwe, możesz używać rel="noopener" (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 okno, które go otwiera, nie będą się kwalifikować do pamięci podręcznej stanu strony internetowej.

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

Jak wspomnieliśmy, po umieszczeniu strony w pamięci podręcznej stanu strony wszystkie zaplanowane zadania JavaScriptu są wstrzymywane, a następnie wznawiane 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 do bieżącej strony, wstrzymanie ich w czasie, 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 itp.), 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 stanu strony internetowej w następujących sytuacjach:

Jeśli Twoja strona korzysta z któregokolwiek z tych interfejsów API, najlepiej zawsze zamykaj połączenia oraz usuwaj lub rozłączaj obserwatorów podczas zdarzenia pagehide lub freeze. Dzięki temu przeglądarka może bezpiecznie buforować stronę, nie ryzykując, że ta zmiana wpłynie na inne otwarte karty.

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

Z przykładu poniżej dowiesz się, jak sprawdzić, czy Twoje strony kwalifikują się do korzystania z pamięci podręcznej stanu strony internetowej podczas korzystania z IndexedDB, 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 is leaving.
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 pamięci podręcznej (Bfcache) oraz zidentyfikować problemy, które uniemożliwiają ich kwalifikację.

Aby przetestować konkretną stronę, otwórz ją w Chrome, a następnie w Narzędziach deweloperskich wybierz Aplikacja > Pamięć podręczna stanu strony internetowej. Następnie kliknij przycisk Uruchom test, a Narzędzia deweloperskie spróbują przejść na inną stronę i z powrotem, aby 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

Jeśli operacja się uda, 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

W przypadku niepowodzenia panel wyświetli informację, że strona nie została przywrócona, wraz z przyczyną tego błędu.

Jeśli jako deweloper możesz zająć się jedną z przyczyn, pojawi się informacja o tym:

Nie udało się przywrócić strony z pamięci podręcznej stanu strony internetowej w Narzędziach deweloperskich

Na zrzucie ekranu powyżej użycie detektora zdarzeń unload uniemożliwia temu, by strona kwalifikowała się do korzystania z pamięci podręcznej stanu strony internetowej. Możesz to naprawić, przełączając się z unload na pagehide:

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

W Lighthouse 10.0 dodaliśmy też kontrolę pamięci podręcznej (bfcache), która pozwala przeprowadzić test podobny do tego, który przeprowadzają Narzędzia deweloperskie, oraz podać powody, dla których strona się nie kwalifikuje, jeśli kontrola się nie powiedzie. Więcej informacji znajdziesz w dokumentacji kontroli bfcache.

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

Jeśli śledzisz odwiedziny w swojej witrynie za pomocą narzędzia analitycznego, możesz zauważyć spadek łącznej liczby odsłon rejestrowanych przez Chrome, ponieważ przeglądarka Chrome nadal włącza pamięć podręczną dla większej liczby użytkowników.

W rzeczywistości już zaniżasz raportowanie wyświetleń stron z innych przeglądarek, które korzystają z pamięci podręcznej stanu strony internetowej, ponieważ większość popularnych bibliotek analitycznych nie śledzi przywracania tej pamięci jako nowych odsłon.

Jeśli nie chcesz, aby liczba wyświetleń stron zmniejszała się z powodu włączenia pamięci podręcznej w Chrome, możesz zgłosić przywrócenie pamięci podręcznej stanu strony internetowej jako odsłony (zalecane), nasłuchując zdarzenia pageshow i sprawdzając właściwość persisted.

Poniższy przykład pokazuje, jak to zrobić za pomocą Google Analytics. Logika ta powinna być podobna do innych narzędzi analitycznych:

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

Pomiar współczynnika trafień bfcache

Warto też śledzić, 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';
    });
  }
});

Patrząc na stosunek back_forward nawigacji do back_forward_cache, można obliczyć współczynnik pamięci podręcznej stanu strony internetowej.

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 i otworzy kartę.

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 (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 części przechodzenia wstecz i do przodu.

Zespół Chrome pracuje nad interfejsem API NotRestoredReasons, który ma pomóc deweloperom ustalić, dlaczego pamięć podręczna nie była używana, i ustalić, dlaczego pamięć podręczna nie jest używana. Być może warto to poprawić w swoich witrynach.

Pomiar skuteczności

bfcache może też negatywnie wpływać na zebrane w polu dane o wydajności, w szczególności na 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 w przypadku zastępowania wczytywania strony przez przywracanie z pamięci podręcznej stanu strony internetowej będzie to prawdopodobnie najkrótsze ładowanie stron w Twoim zbiorze danych. Dzieje się tak dlatego, że 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 wydajność strony w zbiorze danych uległa zwiększeniu, może to spowolnić dystrybucję stron w Twoim zbiorze danych, chociaż prawdopodobnie nastąpił wzrost wydajności.

Istnieje kilka sposobów, które pomogą Ci radzić sobie z tym problemem. Pierwszym z nich jest dodanie adnotacji do wszystkich danych wczytywania strony z odpowiednimi typami nawigacji: navigate, reload, back_forward lub prerender. Dzięki temu możesz nadal monitorować wydajność w ramach tych typów nawigacji, nawet jeśli ogólne odchylenie rozkładu jest ujemne. Ta metoda jest zalecana w przypadku nieukierunkowanych na użytkownika wskaźników wczytywania strony, takich jak czas 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 szybciej niż w przypadku tradycyjnych stron, ważne jest, aby to odzwierciedlały podstawowe wskaźniki internetowe. W końcu użytkownik nie interesuje się tym, czy pamięć podręczna jest włączona, ale zależy mu tylko na tym, że nawigacja była szybka.

Narzędzia takie jak Raport na temat użytkowania Chrome, które zbierają podstawowe wskaźniki internetowe i generują raporty na ich temat, traktują przywrócenie pamięci podręcznej stanu strony internetowej jako oddzielne wizyty na stronach w swoim zbiorze danych.

Chociaż jeszcze nie istnieją (jeszcze) specjalne interfejsy API do pomiaru tych danych po przywróceniu pamięci podręcznej, ich wartości można oszacować za pomocą istniejących internetowych interfejsów API.

  • W przypadku największego wyrenderowania treści (LCP) możesz użyć różnicy między sygnaturą czasową zdarzenia pageshow a sygnaturą następnej wyrenderowanej klatki (ponieważ wszystkie elementy w klatce będą w tym samym czasie wymalowane). Pamiętaj, że w przypadku przywracania pamięci podręcznej (bfcache) wartości LCP i FCP będą takie same.
  • W przypadku Opóźnienie przy pierwszym działaniu (FID) możesz ponownie dodać detektory zdarzeń (te same, których używa FID polyfill) w zdarzeniu pageshow i zgłosić FID jako opóźnienie pierwszego wejścia po przywróceniu pamięci podręcznej.
  • W przypadku skumulowanego przesunięcia układu (CLS) możesz nadal korzystać z dotychczasowego obserwatora skuteczności. Wystarczy, że zresetujesz 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 po poszczególnych podstawowych wskaźnikach internetowych. Konkretny przykład implementacji wersji bfcache tych wskaźników w kodzie znajdziesz w artykule o dodawaniu ich do biblioteki JS Web-vitals.

Dodatkowe materiały