Ograniczanie opóźnień w nawigacji
Często zdarza się, że w momencie zamknięcia strony lub aplikacji przez użytkownika znajdują się na niej nieprzesłane dane analityczne lub inne dane. Aby zapobiec utracie danych, niektóre witryny używają wywołania synchronicznego XMLHttpRequest()
, aby utrzymać stronę lub aplikację otwartą do czasu przekazania danych na serwer. Istnieją lepsze sposoby zapisywania danych, a ta technika powoduje opóźnienie zamykania strony nawet o kilka sekund, co powoduje nieprzyjemne wrażenia użytkownika.
Ta praktyka musi się zmienić, a przeglądarki na to reagują. Specyfikacja XMLHttpRequest()
jest już zaplanowana do wycofania i usunięcia. Chrome 80 podejmuje pierwszy krok, zakazując wywołań synchronicznych w kilku przetwarzaczach zdarzeń, w szczególności beforeunload
, unload
, pagehide
i visibilitychange
, gdy są one wywoływane w ramach odrzucenia. WebKit opublikował też niedawno komit wprowadzający tę samą zmianę zachowania.
W tym artykule opiszę krótko opcje dla osób, które potrzebują czasu na zaktualizowanie swoich witryn, oraz przedstawię alternatywy dla XMLHttpRequest()
.
Tymczasowe wyłączenia
Chrome nie chce po prostu odłączyć XMLHttpRequest()
, dlatego dostępne są tymczasowe opcje rezygnacji. W przypadku witryn w internecie dostępny jest okres próbny.
W ten sposób do nagłówków stron dodasz token dotyczący pochodzenia, który umożliwia asynchroniczne wywołania XMLHttpRequest()
. Ta opcja zostanie wycofana w marcu 2021 r., tuż przed wydaniem Chrome 89. Klienci korzystający z Chrome Enterprise mogą też użyć flagi zasad AllowSyncXHRInPageDismissal
, która wygasa w tym samym czasie.
Alternatywy
Niezależnie od tego, jak wysyłasz dane z powrotem na serwer, nie warto czekać, aż strona się rozładuje, aby wysłać wszystkie dane naraz. Oprócz tego, że powoduje nieprzyjemne wrażenia użytkownika, unload jest niepewnym rozwiązaniem w przypadku nowoczesnych przeglądarek i może spowodować utratę danych, jeśli coś pójdzie nie tak. W szczególności zdarzenia unload często nie są wywoływane w przeglądarkach mobilnych, ponieważ w systemach operacyjnych urządzeń mobilnych istnieje wiele sposobów na zamknięcie karty lub przeglądarki bez wywołania zdarzenia unload
.
W przypadku XMLHttpRequest()
używanie małych ładunków było opcjonalne. Teraz jest to wymagane. Obie te opcje mają limit przesyłania wynoszący 64 KB na kontekst, zgodnie z wymaganiami specyfikacji.
Pobieranie informacji o utrzymywaniu aktywności
Interfejs Fetch API zapewnia niezawodne narzędzie do obsługi interakcji z serwerem oraz spójny interfejs do stosowania w różnych interfejsach API platform. Jedną z opcji jest keepalive
, która zapewnia, że żądanie jest kontynuowane niezależnie od tego, czy strona, która je wywołała, pozostaje otwarta:
window.addEventListener('unload', {
fetch('/siteAnalytics', {
method: 'POST',
body: getStatistics(),
keepalive: true
});
}
Metoda fetch()
ma tę zaletę, że zapewnia większą kontrolę nad tym, co jest wysyłane do serwera. W przykładzie nie pokazuję, że funkcja fetch()
zwraca również obietnicę, która rozwiązuje się z obiektem Response
. Ponieważ próbuję pozbyć się sposobu wczytywania strony, nie robiłem z tym nic.
SendBeacon()
SendBeacon()
w podstawie korzysta z interfejsu Fetch API, dlatego ma to samo ograniczenie ładunku 64 KB i zapewnia, że żądanie jest kontynuowane po usunięciu strony. Jego główną zaletą jest prostota. Umożliwia on przesyłanie danych za pomocą jednego wiersza kodu:
window.addEventListener('unload', {
navigator.sendBeacon('/siteAnalytics', getStatistics());
}
Podsumowanie
Dzięki zwiększonej dostępności
fetch()
w różnych przeglądarkach XMLHttpRequest()
zostanie w pewnym momencie prawdopodobnie usunięta z platformy internetowej. Dostawcy przeglądarek zgadzają się, że należy je usunąć, ale zajmie to trochę czasu. Wycofanie jednej z najgorszych opcji użycia to pierwszy krok, który poprawia wrażenia użytkowników.
Zdjęcie: Matthew Hamilton, Unsplash