IndexedDB vs localStorage: którą pamięć przeglądarki wybrać
IndexedDB vs localStorage
IndexedDB vs localStorage: limity, szybkość, kiedy używać | We.Inc
Porównanie IndexedDB i localStorage: limity rozmiaru w każdej przeglądarce, sync vs async, co każde z nich może przechowywać, plus demo zapisujące jedną notatkę w obu.
Wybierz localStorage dla kilku drobnych ustawień: przechowuje tylko tekst, około 5 MiB na pochodzenie, a każde wywołanie blokuje stronę, dopóki się nie zakończy. Wybierz IndexedDB dla prawdziwych danych: jest asynchroniczne, transakcyjne, przechowuje obiekty, daty i pliki, a jego limit to część dysku. Demo poniżej zapisuje jedną notatkę w obu.
Wersja skrócona
Pytanie
localStorage
IndexedDB
Co może przechowywać?
Tylko tekst
Wszystko, co kopiuje algorytm structured clone, w tym Blob i File
Rozmiar
Do 5 MiB na pochodzenie
Część wolnego dysku, zależnie od przeglądarki
Blokuje stronę?
Tak, każde wywołanie jest synchroniczne
Nie, wyniki przychodzą przez zdarzenia lub promise
Transakcje i indeksy
Nie
Tak
Dostępne w Web Workerze
Nie, to właściwość window
Tak
Najlepsze do
Motywu, ostatniej karty, roboczego tekstu
Danych offline, cache, plików, wszystkiego, co przeszukujesz
Oba API przechowują dane w przeglądarce odwiedzającego po zamknięciu karty i oba są ograniczone do pochodzenia strony. Różnica tkwi w wadze. localStorage to mała synchroniczna mapa tekstów, którą opanujesz w minutę; IndexedDB to niewielka baza danych z wersjami, magazynami obiektów i transakcjami. Ta strona pokazuje prawdziwe limity z dokumentacji i pozwala zobaczyć, co każde z nich zwraca.
Wpisz notatkę i naciśnij Zapisz w obu. Strona zapisuje ją w localStorage jako tekst JSON, a w magazynie obiektów IndexedDB jako prawdziwy obiekt.
Naciśnij Odczytaj. Panel wyników pokazuje typ zwrócony przez każde API: tekst z localStorage, obiekt z działającym Date z IndexedDB.
Naciśnij Sprawdź limit, aby zapytać navigator.storage.estimate(), ile to pochodzenie zużywa i ile może zużyć. Liczby są szacunkowe.
Naciśnij Wyczyść dane demo, aby usunąć klucz demo i skasować bazę demo. Nic nie opuszcza Twojego urządzenia.
Owiń localStorage.setItem w try...catch. Pełny magazyn rzuca QuotaExceededError, a niektóre ustawienia prywatności rzucają SecurityError przy pierwszym dostępie.
Zapisuj w localStorage wynik JSON.stringify i parsuj go przy odczycie. Daty wracają jako tekst, więc musisz je przekonwertować samodzielnie.
W IndexedDB mała nakładka, taka jak idb lub Dexie, zamienia styl żądań i zdarzeń na promise i oszczędza mnóstwo powtarzalnego kodu.
Wywołuj navigator.storage.persist() tylko dla danych, których utrata zmartwiłaby użytkownika, na przykład dokumentów offline. W przeciwnym razie przeglądarka może je usunąć, gdy zabraknie miejsca.
Nigdy nie trzymaj sekretów ani tokenów sesji w żadnym z tych magazynów. Każdy skrypt działający na stronie może je odczytać.
Najczęściej zadawane pytania
Ile może pomieścić localStorage?
MDN dokumentuje limit 5 MiB dla local storage i 5 MiB dla session storage na pochodzenie, łącznie 10 MiB. Ponieważ wartości to teksty UTF-16, liczba mieszczących się znaków może być mniejsza, niż się spodziewasz. Przekroczenie limitu rzuca QuotaExceededError.
Ile może pomieścić IndexedDB?
To zależy od przeglądarki i dysku. Przeglądarki oparte na Chromium pozwalają pochodzeniu zająć do 60% całkowitego rozmiaru dysku. Firefox w trybie best-effort pozwala na mniejszą z wartości: 10% dysku lub 10 GiB na grupę witryn. Aplikacja przeglądarki Safari pozwala na około 60% dysku. Użyj navigator.storage.estimate(), aby odczytać prawdziwą wartość.
Czy IndexedDB jest szybsze niż localStorage?
Dla jednej małej wartości localStorage jest zwykle szybsze do napisania w kodzie i wystarczająco szybkie w działaniu. Problem w tym, że jest synchroniczne, więc duże odczyty i zapisy zamrażają główny wątek. IndexedDB wykonuje pracę poza głównym przepływem i informuje Cię, gdy skończy, dzięki czemu przewijanie i pisanie pozostają płynne.
Czy przeglądarka może usunąć moje dane z IndexedDB?
Tak. Domyślnie pamięć działa w trybie best-effort, więc przeglądarka może usunąć dane pochodzenia, gdy na dysku brakuje miejsca. Wywołanie navigator.storage.persist() przełącza na tryb trwały, w którym tylko użytkownik może je wyczyścić. Firefox pokazuje prośbę o zgodę; Chrome i Safari decydują na podstawie tego, jak użytkownik korzysta z witryny.
Czy używać localStorage do tokena logowania?
Nie. Każdy skrypt na stronie, także wstrzyknięty, może odczytać localStorage i IndexedDB. Trzymaj identyfikatory sesji w cookies oznaczonych jako HttpOnly, Secure i SameSite, których skrypty strony nie mogą odczytać.
Dlaczego synchroniczność ma znaczenie
Gdy kod wywołuje localStorage.getItem, przeglądarka wstrzymuje wykonywanie innego JavaScriptu, dopóki wartość nie wróci z dysku. Przy nazwie motywu nikt tego nie zauważy. Przy kilku megabajtach JSON parsowanych przy każdym ładowaniu strony objawia się to przerwą, zanim strona zareaguje na dotknięcia.
IndexedDB od razu zwraca obiekt żądania, a success lub error wywołuje później. Taki kształt wymaga więcej kodu, dlatego większość projektów używa nakładki opartej na promise, ale nigdy nie trzyma strony jako zakładnika.
Tekst vs structured clone
localStorage zamienia wszystko w tekst. Zapisz liczbę 3, a odczytasz tekst "3"; zapisz obiekt bez JSON.stringify, a odczytasz "[object Object]".
IndexedDB kopiuje wartości algorytmem structured clone, więc Date pozostaje Date, Map pozostaje Map, a Blob lub File można zapisać bez zmian. Właśnie to czyni je odpowiednim dla obrazów offline, nagranego dźwięku lub szkiców z załącznikami.
Prosta zasada wyboru
Jeśli dane mieszczą się w jednej krótkiej linii i odczytujesz je raz przy starcie, localStorage wystarczy. Jeśli chcesz je przeszukiwać, liczyć, stronicować, przechowywać w nich pliki binarne lub aktualizować je z service workera, użyj IndexedDB.
Trzecią opcją, często lepszą od obu, są dane na serwerze: jeśli użytkownik oczekuje, że zobaczy to samo na innym urządzeniu, dane należą do Twojej bazy danych, a pamięć przeglądarki służy tylko jako cache.
Limity pamięci według przeglądarki
Wartości zgodnie ze stroną MDN o limitach pamięci. IndexedDB, Cache API i origin private file system dzielą ten sam limit.
Limit na pochodzenie
Przeglądarka
localStorage
IndexedDB (best-effort)
IndexedDB (trwałe)
Chrome, Edge i inne oparte na Chromium
5 MiB
Do 60% całego dysku
Do 60% całego dysku
Firefox
5 MiB
Mniejsza z wartości: 10% dysku lub 10 GiB na grupę witryn
Do 50% dysku, maksymalnie 8 TiB
Aplikacja przeglądarki Safari
5 MiB
Około 60% całego dysku
Około 60% całego dysku
Aplikacje osadzające treści webowe (WebKit)
5 MiB
Około 15% całego dysku
Około 15% całego dysku
Ten sam zapis w obu API
localStorage: stringify, zabezpieczenie, parse
try...catch obsługuje pełny lub zablokowany magazyn. Datę trzeba odtworzyć ręcznie po parsowaniu.
IndexedDB: otwarcie, upgrade, zapis w transakcji
onupgradeneeded uruchamia się za pierwszym razem i za każdym razem, gdy rośnie numer wersji; to jedyne miejsce, w którym można tworzyć magazyny obiektów.
Zapytaj, ile masz miejsca, i poproś o jego zachowanie
estimate() zwraca przybliżoną liczbę bajtów. persist() zwraca true, jeśli przeglądarka przyznała trwałą pamięć.
Zapisz jedną notatkę w obu magazynach
To demo działa wyłącznie w Twojej przeglądarce. Zapisuje dane pod kluczem we-demo-note i w bazie o nazwie we-demo-db, a przycisk Wyczyść usuwa oba.
Notatka do zapisania
Zadzwonić do drukarni w piątek
Zapisz w obu
Odczytaj
Sprawdź limit
Wyczyść dane demo
Jeszcze nic nie odczytano. Zapisz notatkę, a potem naciśnij Odczytaj.
localStorage zwróciło
IndexedDB zwróciło
Typ: {v}
savedAt jest obiektem Date: {v}
Nic nie zapisano
Notatka zapisana w localStorage i IndexedDB.
Klucz demo i baza danych usunięte.
To pochodzenie zużywa około {n} MB z mniej więcej {v} MB dostępnych.
Ta przeglądarka nie udostępnia navigator.storage.estimate().