Rozdiel medzi cookies a localStorage #
localStorage umožňuje prehliadačom ukladať dáta súvisiace s aplikáciou na
strane klienta. Môže sa to zdať identické s účelom cookies, ale sú tu
rozdiely, inak by sa to mohlo jednoducho nazývať otherCookies namiesto
localStorage.
Po prvé, od localStorage sa očakáva, že bude synchronizovať naprieč viacerými kartami a oknami, zatiaľ čo pri cookies sa správanie líši naprieč prehliadačmi a nie je všeobecne konzistentné. Za nekonzistentnosti by som vinil fakt, že cookies sú staršia technológia a boli navrhnuté s iným cieľom.
Ďalší rozdiel je ten, že cookies, ak sú prítomné, sa pripájajú ku každej požiadavke používateľa. Pre čo najlepší používateľský zážitok je vhodné udržiavať výmenu dát medzi serverom a klientom na minime. Hoci žijeme vo svete, kde rýchlosti pripojení neustále rastú, vidiecke a vzdialené oblasti majú tendenciu nasledovať oveľa pomalším tempom. Eliminácia zbytočných dát z komunikácie výrazne pomáha. Posielanie megabajtov v cookies pri každej požiadavke je rozhodne správna cesta pri budovaní elegantnej aplikácie.
Cookies, na rozdiel od localStorage, majú dátum vypršania platnosti. Sú tiež cieľom rôznych foriem čistiacich alebo softvérov na ochranu súkromia. V takom scenári by mohol byť používateľ rád, že si uvoľnil miesto na zariadení, pričom súčasne riešil obavy o súkromie, len aby zistil, že práca, ktorú v aplikácii vykonal, sa už neuložila. Spoliehať sa výlučne na localStorage na ukladanie pracovných dát používateľa taktiež nie je správna cesta, pretože môže byť vymazaný pri čistení cache prehliadača.
Nakoniec, localStorage nie je priamo dostupný na serveri, len na klientovi. Cookies sú dostupné na oboch stranách. API na ich spracovanie je teda tiež odlišné. Sú jasne určené na rôzne úlohy.
Tu je jednoduché porovnanie textu vyššie:
| rozdiel | cookie | localStorage |
|---|---|---|
| Expirácia | áno | nie |
| Prístupnosť | server aj klient | len klient |
| Dostupnosť | pri každej požiadavke | manuálny prístup |
| Synchronizácia kariet | rôzne naprieč prehliadačmi | vstavané |
Svelte a localStorage #
Keďže som potreboval mať perzistentné reaktívne dáta v Svelte aplikácii, rozhodol som sa problém riešiť tým, že začnem s existujúcim príkladom z REPL.
Na spustenie príkladu ho musíte stiahnuť, keďže v sandboxovanom prostredí
nefunguje. Urobil som to za vás. Príklad nebol vhodný pre moju aplikáciu.
Mal dve nežiaduce vlastnosti, ktoré som musel opraviť. Po prvé, pri úplne
prvom načítaní (alebo po vymazaní localStorage) store obsahoval hodnotu
null. Po druhé, nefungoval s poliami.
Pre referenciu, príkladový kód samotného store vyzeral takto:
import { writable } from "svelte/store"
const storedTheme = localStorage.getItem("theme")
export const theme = writable(storedTheme)
theme.subscribe(value => {
localStorage.setItem("theme", value === "dark" ? "dark" : "light")
})
Prvé načítanie #
Chvíľu mi trvalo pochopiť, prečo kód vracia null, hoci je tam predvolená hodnota zakotvená vo forme ternárneho operátora:
value === "dark" ? "dark" : "light"
Stalo sa mi jasným, že táto metóda sa týka len ukladania, nie
načítavania. Keď je localStorage prázdny, načítaná hodnota je null,
ktorá sa potom odovzdá do writable store. Metóda .subscribe store sa teda
volá, keď chceme hodnotu store .set, čo je príliš neskoro v životnom
cykle. Zmena musela byť vykonaná pri inicializácii writable store, pretože
jeho prvý argument určuje, odkiaľ hodnota store pôvodne pochádza.
import { writable } from "svelte/store"
const itemName = "storedArray"
const retrieved = localStorage.getItem(itemName)
export const storedArray = writable(parsed === null ? [] : retrieved)
storedArray.subscribe(value => localStorage.setItem(itemName, retrieved))
Tento prístup by fungoval, nebyť jedného faktu, ktorý ma prekvapil, keď som ho prvýkrát objavil:
localStorage nepodporuje polia, len reťazce
Presne tak — localStorage nepodporuje dátové štruktúry, len skaláre. Existujú zrejmé spôsoby, ako obísť toto obmedzenie, akonáhle si ho uvedomíte. Objavenie toho bola tá ťažká časť, pretože prehliadač nevyhodil žiadnu chybu pri pokuse uložiť pole do localStorage. Prezeranie obsahu localStorage pomocou nástrojov, ktoré prehliadač poskytuje, zobrazilo hodnoty pekne oddelené čiarkou, čo sa veľmi podobalo poľu.
Polia v localStorage #
Našťastie tento problém už problémom nie je. Na konverziu dátovej štruktúry
na reťazec ju môžeme serializovať. Bežný spôsob v JS je konverzia do JSON
pomocou JSON.stringify(). Na spätné prevesenie použijeme JSON.parse().
import { writable } from "svelte/store"
const itemName = "storedArray"
const retrieved = localStorage.getItem(itemName)
const parsed = JSON.parse(retrieved)
export const storedArray = writable(parsed === null ? [] : parsed)
storedArray.subscribe(value =>
localStorage.setItem(itemName, JSON.stringify(value))
)
Teraz môžete aj vy pracovať s perzistentným store obsahujúcim pole vo svojom Svelte projekte. Ako poznámka na okraj, keďže objekty v JS môžu byť tiež serializované do JSON (pretože JSON je v skutočnosti javascript Object Notation, vytvorený špeciálne na tento účel), tento prístup sa dá ľahko upraviť na ukladanie objektov v localStorage.
Kód, ktorý opäť kvôli sandboxovaniu nebude fungovať priamo v REPL, alebo sa dá naklonovat z repozitára a spustiť lokálne.
Ďalšie čítanie #
- https://svelte.dev/docs#svelte_store
- https://chasingcode.dev/blog/svelte-persist-state-to-localstorage/
- https://www.tutorialspoint.com/What-is-the-difference-between-local-storage-vs-cookies
- https://stackoverflow.com/questions/3357553/how-do-i-store-an-array-in-localstorage
- https://stackoverflow.com/questions/57089227/inconsistency-when-writing-synchronous-to-localstorage-from-multiple-tabs