Istnieje wiele różnych opcji przechowywania danych w przeglądarce. Która z nich jest najlepsza dla Twoich potrzeb?
Połączenia internetowe mogą być niestabilne lub niedostępne w podróży, dlatego obsługa offline i niezawodne działanie to typowe funkcje w progresywnych aplikacjach internetowych. Nawet w idealnych warunkach bezprzewodowych rozsądne korzystanie z pamięci podręcznej i innych technik przechowywania danych może znacznie poprawić komfort użytkownika. Istnieje kilka sposobów zapisywania w pamięci podręcznej statycznych zasobów aplikacji (HTML, JavaScript, CSS, obrazy itp.) i danych (dane użytkownika, artykuły z wiadomościami itp.). Które rozwiązanie jest najlepsze? Ile danych możesz przechowywać? Jak zapobiec ich usunięciu?
Czego mam użyć?
Oto ogólne zalecenie dotyczące przechowywania zasobów:
- W przypadku zasobów sieciowych niezbędnych do wczytania aplikacji, użyj interfejsu Cache Storage API (część service workerów).
- W przypadku treści opartych na plikach użyj Origin Private File System (OPFS).
- W przypadku innych danych użyj IndexedDB (z otoczką obietnic).
Interfejsy IndexedDB, OPFS i Cache Storage API są obsługiwane w każdej nowoczesnej przeglądarce.
Są asynchroniczne i nie blokują wątku głównego (ale istnieje też synchroniczna wersja OPFS, która jest dostępna tylko w instancjach roboczych). Są dostępne z obiektu window, instancji roboczych i service workerów, dzięki czemu można ich używać w dowolnym miejscu kodu.
A co z innymi mechanizmami przechowywania danych?
W przeglądarce dostępnych jest kilka innych mechanizmów przechowywania danych, ale mają one ograniczone zastosowanie i mogą powodować poważne problemy z wydajnością.
SessionStorage jest specyficzny dla karty i ograniczony do czasu jej trwania. Może być przydatny do przechowywania niewielkich ilości informacji specyficznych dla sesji, np. klucza IndexedDB. Należy go używać ostrożnie, ponieważ jest synchroniczny i blokuje wątek główny. Jest ograniczony do około 5 MB i może zawierać tylko ciągi znaków. Ponieważ jest specyficzny dla karty, nie jest dostępny z instancji roboczych ani service workerów.
Należy unikać LocalStorage, ponieważ jest synchroniczny i blokuje wątek główny. Jest ograniczony do około 5 MB i może zawierać tylko ciągi znaków. LocalStorage nie jest dostępny z instancji roboczych ani service workerów.
Pliki cookie mają swoje zastosowania, ale nie należy ich używać do przechowywania danych. Pliki cookie są wysyłane z każdym żądaniem HTTP, więc przechowywanie w nich większej ilości danych znacznie zwiększy rozmiar każdego żądania internetowego. Są synchroniczne i nie są dostępne z instancji roboczych. Podobnie jak LocalStorage i SessionStorage, pliki cookie są ograniczone tylko do ciągów znaków.
Interfejs File System Access API został zaprojektowany tak, aby użytkownicy mogli odczytywać i edytować pliki w lokalnym systemie plików. Zanim strona będzie mogła odczytać lub zapisać dowolny plik lokalny, użytkownik musi przyznać jej uprawnienia. Uprawnienia nie są zachowywane między sesjami, chyba że uchwyt pliku jest przechowywany w pamięci podręcznej IndexedDB. Interfejs File System Access API najlepiej sprawdza się w takich przypadkach jak edytory, w których trzeba otworzyć plik, zmodyfikować go, a następnie zapisać zmiany.
Interfejsy File System API i FileWriter API udostępniają metody odczytywania i zapisywania plików w systemie plików w piaskownicy. Chociaż jest asynchroniczny, nie jest zalecany, ponieważ jest dostępny tylko w przeglądarkach opartych na Chromium.
Ile danych mogę przechowywać?
Krótko mówiąc, bardzo dużo – co najmniej kilkaset megabajtów, a potencjalnie setki gigabajtów lub więcej. Implementacje przeglądarek różnią się, ale ilość dostępnego miejsca na dane zależy zwykle od ilości miejsca dostępnego na urządzeniu.
- Chrome umożliwia przeglądarce wykorzystanie do 80% łącznej ilości miejsca na dysku. Źródło może wykorzystać do 60% łącznej ilości miejsca na dysku. Aby określić maksymalny dostępny limit, możesz użyć interfejsu StorageManager
API. Inne przeglądarki oparte na Chromium mogą się różnić.
- W trybie incognito Chrome zmniejsza ilość miejsca na dane, z którego może korzystać źródło, do około 5% łącznej ilości miejsca na dysku.
- Jeśli użytkownik włączy w Chrome opcję „Wyczyść pliki cookie i dane witryn w momencie zamknięcia wszystkich okien”, limit miejsca na dane zostanie znacznie zmniejszony do maksymalnie około 300 MB.
- Firefox umożliwia przeglądarce wykorzystanie do 50% wolnego miejsca na dysku. Grupa
eTLD+1 (np.
example.com,www.example.comifoo.bar.example.com) może wykorzystać do 2 GB. Aby sprawdzić, ile miejsca jest jeszcze dostępne, możesz użyć interfejsu StorageManager API. - Safari (zarówno na komputerach, jak i urządzeniach mobilnych) wydaje się zezwalać na około 1 GB. Po osiągnięciu limitu Safari wyświetli użytkownikowi prośbę o zwiększenie limitu o 200 MB. Nie udało mi się znaleźć żadnej oficjalnej dokumentacji na ten temat.
- Jeśli PWA zostanie dodana do ekranu głównego w Safari na urządzeniu mobilnym, utworzy nowy kontener miejsca na dane, a PWA i Safari na urządzeniu mobilnym nie będą współdzielić żadnych danych. Po osiągnięciu limitu zainstalowanej PWA nie ma możliwości poproszenia o dodatkowe miejsce na dane.
W przeszłości, jeśli witryna przekroczyła określony próg przechowywanych danych, przeglądarka wyświetlała użytkownikowi prośbę o przyznanie uprawnień do korzystania z większej ilości danych. Jeśli na przykład źródło wykorzystywało więcej niż 50 MB, przeglądarka wyświetlała użytkownikowi prośbę o zezwolenie na przechowywanie do 100 MB, a następnie ponownie wyświetlała prośbę co 50 MB.
Obecnie większość nowoczesnych przeglądarek nie wyświetla użytkownikowi prośby i zezwala witrynie na wykorzystanie dozwolonego limitu. Wyjątkiem jest Safari, która wyświetla prośbę po przekroczeniu limitu miejsca na dane, prosząc o zgodę na zwiększenie przydzielonego limitu. Jeśli źródło spróbuje wykorzystać więcej niż przydzielony limit, dalsze próby zapisania danych nie powiodą się.
Jak sprawdzić, ile miejsca jest dostępne?
W wielu przeglądarkach możesz użyć interfejsu StorageManager API, aby określić ilość miejsca dostępnego dla źródła i ilość miejsca, z którego korzysta. Zgłasza łączną liczbę bajtów używanych przez IndexedDB i Cache API oraz umożliwia obliczenie przybliżonej ilości pozostałego miejsca na dane.
if (navigator.storage && navigator.storage.estimate) {
const quota = await navigator.storage.estimate();
// quota.usage -> Number of bytes used.
// quota.quota -> Maximum number of bytes available.
const percentageUsed = (quota.usage / quota.quota) * 100;
console.log(`You've used ${percentageUsed}% of the available storage.`);
const remaining = quota.quota - quota.usage;
console.log(`You can write up to ${remaining} more bytes.`);
}
Musisz przechwytywać błędy przekroczenia limitu (patrz poniżej). W niektórych przypadkach dostępny limit może przekraczać rzeczywistą ilość dostępnego miejsca na dane.
Zbadaj
Podczas programowania możesz użyć Narzędzi deweloperskich w przeglądarce, aby sprawdzić różne typy pamięci masowej i wyczyścić wszystkie przechowywane dane.
W Chrome 88 dodano nową funkcję, która umożliwia zastąpienie limitu miejsca na dane witryny w panelu Miejsce. Ta funkcja umożliwia symulowanie różnych urządzeń i testowanie działania aplikacji w scenariuszach, w których jest mało miejsca na dysku. Otwórz Aplikacja , a potem Miejsce , zaznacz pole wyboru Symuluj niestandardowy limit miejsca na dane i wpisz dowolną prawidłową liczbę, aby zasymulować limit miejsca na dane.
Podczas pracy nad tym przewodnikiem napisałem proste narzędzie, które ma na celu szybkie wykorzystanie jak największej ilości miejsca na dane. To szybki sposób na eksperymentowanie z różnymi mechanizmami przechowywania danych i sprawdzenie, co się stanie, gdy wykorzystasz cały limit.
Jak radzić sobie z przekroczeniem limitu?
Co zrobić, gdy przekroczysz limit? Przede wszystkim zawsze należy przechwytywać i obsługiwać błędy zapisu, niezależnie od tego, czy jest to QuotaExceededError, czy coś innego. Następnie, w zależności od projektu aplikacji, zdecyduj, jak sobie z tym poradzić.
Możesz na przykład usunąć treści, do których nie uzyskiwano dostępu od dłuższego czasu, usunąć dane na podstawie rozmiaru lub umożliwić użytkownikom wybranie, co chcą usunąć.
Gdy przekroczysz dostępny limit, zarówno IndexedDB, jak i Cache API zgłoszą błąd DOMError o nazwie QuotaExceededError.
IndexedDB
Jeśli źródło przekroczy limit, próby zapisu w IndexedDB nie powiodą się. Zostanie wywołany moduł obsługi onabort() transakcji, który przekaże zdarzenie.
Zdarzenie będzie zawierać DOMException we właściwości error. Sprawdzenie name błędu zwróci QuotaExceededError.
const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
const error = event.target.error; // DOMException
if (error.name == 'QuotaExceededError') {
// Fallback code goes here
}
};
Cache API
Jeśli źródło przekroczy limit, próby zapisu w Cache API zostaną odrzucone z błędem QuotaExceededError DOMException.
try {
const cache = await caches.open('my-cache');
await cache.add(new Request('/sample1.jpg'));
} catch (err) {
if (error.name === 'QuotaExceededError') {
// Fallback code goes here
}
}
Jak działa usuwanie?
Pamięć internetowa jest podzielona na 2 zasobniki: „Najlepsze rozwiązanie” i „Trwałe”. „Najlepsze rozwiązanie” oznacza, że przeglądarka może wyczyścić pamięć bez przerywania pracy użytkownika, ale jest ona mniej trwała w przypadku długoterminowych lub krytycznych danych. Pamięć trwała nie jest automatycznie czyszczona, gdy ilość miejsca na dane jest mała. Użytkownik musi ręcznie wyczyścić tę pamięć (w ustawieniach przeglądarki).
Domyślnie dane witryny (w tym IndexedDB, Cache API itp.) należą do kategorii „Najlepsze rozwiązanie”, co oznacza, że jeśli witryna nie poprosi o trwałe miejsce na dane, przeglądarka może według własnego uznania usunąć dane witryny, np. gdy ilość miejsca na urządzeniu jest mała.
Zasady usuwania w przypadku „Najlepszego rozwiązania” są następujące:
- Przeglądarki oparte na Chromium zaczną usuwać dane, gdy zabraknie miejsca, najpierw usuwając wszystkie dane witryny z najrzadziej używanego źródła, a potem z następnego, aż przeglądarka nie przekroczy limitu.
- Firefox zacznie usuwać dane, gdy skończy się dostępne miejsce na dysku, najpierw usuwając wszystkie dane witryny z najrzadziej używanego źródła, a potem z następnego, aż przeglądarka nie przekroczy limitu.
- Safari wcześniej nie usuwała danych, ale niedawno wprowadziła nowy 7-dniowy limit dla wszystkich zapisywalnych miejsc na dane (patrz poniżej).
Od wersji iOS i iPadOS 13.4 oraz Safari 13.1 na macOS obowiązuje 7-dniowy limit dla wszystkich miejsc na dane, do których skrypt może zapisywać dane, w tym IndexedDB, rejestracja service workera i Cache API. Oznacza to, że jeśli użytkownik nie będzie wchodzić w interakcję z witryną, Safari usunie całą zawartość z pamięci podręcznej po 7 dniach korzystania z Safari. Te zasady usuwania nie dotyczą zainstalowanych PWA dodanych do ekranu głównego. Więcej informacji znajdziesz w artykule Full Third-Party Cookie Blocking and More na blogu WebKit.
Zasobniki na dane
Głównym założeniem interfejsu Storage Buckets API jest umożliwienie witrynom tworzenia wielu zasobników na dane, z których każdy może zostać usunięty przez przeglądarkę niezależnie od innych zasobników. Umożliwia to programistom określenie priorytetu usuwania, aby mieć pewność, że najważniejsze dane nie zostaną usunięte.
Bonus: dlaczego warto używać otoczki dla IndexedDB
IndexedDB to interfejs API niskiego poziomu, który wymaga znacznej konfiguracji przed użyciem, co może być szczególnie uciążliwe w przypadku przechowywania danych o niskiej złożoności. W przeciwieństwie do większości nowoczesnych interfejsów API opartych na obietnicach jest on oparty na zdarzeniach. Otoczki obietnic, takie jak idb dla IndexedDB, ukrywają niektóre zaawansowane funkcje, ale co ważniejsze, ukrywają złożony mechanizm (np. transakcje, wersjonowanie schematu) związany z biblioteką IndexedDB.
Bonus: SQLite Wasm
Po wycofaniu i usunięciu Web SQL z Chrome Google współpracował z opiekunami popularnej bazy danych SQLite, aby zaoferować zamiennik Web SQL oparty na SQLite. Więcej informacji o tym, jak go używać, znajdziesz w artykule SQLite Wasm in the browser backed by the Origin Private File System.
Podsumowanie
Czasy ograniczonego miejsca na dane i wyświetlania użytkownikowi prośby o przechowywanie coraz większej ilości danych już minęły. Witryny mogą przechowywać praktycznie wszystkie zasoby i dane potrzebne do działania. Za pomocą interfejsu StorageManager API możesz określić, ile miejsca jest dostępne i ile zostało wykorzystane. Dzięki pamięci trwałej możesz chronić je przed usunięciem, chyba że użytkownik je usunie.
Dodatkowe materiały
- Sprawdzone metody korzystania z IndexedDB
- Pojęcia dotyczące miejsca na dane i limitów w Chrome Web Storage
Dziękujemy
Szczególne podziękowania dla Jarryda Goodmana, Phila Waltona, Eijiego Kitamury, Daniela Murphy’ego, Darwina Huanga, Josha Bella, Marijna Kruisselbrinka i Victora Costana za sprawdzenie tego przewodnika. Dziękujemy Eijiemu Kitamurze, Addy’emu Osmaniemu i Marcowi Cohenowi, którzy napisali oryginalne artykuły, na których opiera się ten przewodnik. Eiji napisał przydatne narzędzie o nazwie Browser Storage Abuser, które pomogło w sprawdzeniu bieżącego działania. Umożliwia ono przechowywanie jak największej ilości danych i sprawdzanie limitów miejsca na dane w przeglądarce. Dziękujemy François Beaufortowi, który zbadał Safari, aby określić limity miejsca na dane, oraz Thomasowi Steinerowi za dodanie informacji o systemie plików Origin Private File System, zasobnikach na dane, SQLite Wasm i ogólną aktualizację treści w 2024 r.