Client-side Storage
tl;dr
Below
5MB
, an effective design pattern is tofetch
/XHR
docs per REST/JSON API, store the network payload as is (serialized JSON; string), yet parse and maintain the payload as the in-memory state store (object/array); repeating this parse-per-net when stale, which is observable per Etag or some such. This is buildable into a synch scheme.Note that JSON parses faster than POJO (Plain Old Javascript Obj). It is often less perfomant to parse JSON payload into POJO and then store/pull data to/from, per object key; a scheme relying much, much more on these flakey (browser-variant) storage APIs.
Document Stores
- @ Browser —
Cache
/CacheStorage
Interface
(a.k.a.Cache
API) is a document store; stores URL-addressable resources per Request/Response (k/v
) pairs; aServiceWorker
API interface; not well supported. Hard limit on cache size, per browser, per origin.
- Workbox is the latest/leanest way to auto-generate a Service Worker (
.js
) and its associated manifest (.json
), and to handle theCache
document store, andIndexedDB
as application state store. - Synch schemes
- Background Sync API (Chrome only); a
ServiceWorker
API
- Background Sync API (Chrome only); a
- Workbox is the latest/leanest way to auto-generate a Service Worker (
- @ Android — SQLcipher (@ GitHub); an encrypted database; an extension of SQLite. Used by WeChat app (
EnMicroMsg.db
). SeeTech.Stacks
(- Web Storage API includes two
k-v
stores; value must be string; per domain; insecure;5MB
limit; well supported, though not available atWeb Worker
; use for small amounts of data. Unlike Cookie API, this is readable by client only. Insecure. Do not store JWTs here.sessionStorage
; available for the duration of the page session.localStorage
; same, but persists even when browser closed/reopened.store.js
(12KB
) @IndexedDB
(API); value can be anything (JS object); a transactional, asynchronous α store that returns notifications per DOM Events (onsuccess
,onerror
,oncomplete
, …); well supported;IDBDatabase
interface; RDBM-type key-indexed for high-performance β ; accessible per same-origin policy; storage limited per browser scheme(s). Intro. Best Practices.5MB
-10MB
, per browser vendor.- Successor to Web SQL Database API.
- Available at
Web Workers
. - Wrappers/Libraries (smallest to biggest):
idb
idb-keyval
; subset ofidb
.
- LocalForage (
28KB
); fallback toWebSQL
, then tolocalStorage
; simple but powerful API. - Dexie.js (
55KB
); + synch (beta). - PouchDB (
121KB
) / RxDB (500KB
); synch per CouchDB sync protocol; fallback toWebSQL
. - Synch schemes
- CouchDB / PouchDB; CouchDB is a JSON (document) store and (Erlang) server; has its own synch protocol; API (CRUD) is HTTP/REST; distributed architecture, with bi-direction replication and synchronization; designed to handle off-line app operations.
- Firebase; Google's mobile web-app platform; vendor lock-in (superglued to GCP); messaging, OAuth, storage (RT database), and hosting.
- CouchDB / PouchDB; CouchDB is a JSON (document) store and (Erlang) server; has its own synch protocol; API (CRUD) is HTTP/REST; distributed architecture, with bi-direction replication and synchronization; designed to handle off-line app operations.
- α — Do not store JSON payload as one big complex object (value) under one key because … The larger the object, the longer the blocking time … increase write errors … cause the browser tab to crash or become unresponsive.
- β — IndexedDB isn’t as performant as believed … blocks the DOM significantly in Firefox and Chrome … slower than both LocalStorage and WebSQL for basic key-value insertions.
For performance comparison between the two key-value stores, see lab @
DEV/front-end/js/storage/localStorage-vs-IndexedDB
. ImmortalDB (
50KB
)
A persistentk-v
store; wraps all the browser'sk-v
stores, and stores redundantly;cookie
,IndexedDB
,localStorage
, and atsessionStorage
; self heals.- Utilizes
idb-keyval
andjs-cookie
.
- Utilizes
Web SQL Database API.
- Precursor to
IndexedDB
API. - No adoption beyond Google Chrome and Android Browser (2010)
- Precursor to
HTTP cookies (
4KB
)- HTTP Headers
Cookie
@ RequestCookie: <cookie-list> Cookie: name=value Cookie: name=value; name2=value2; name3=value3
Set-Cookie
@ ResponseSet-Cookie: <cookie-name>=<cookie-value> Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
- For storing sensitive data; a small piece of data sent by server. Client may store and send it back with next request to same server.
- Browser automatically adds
Cookie
header per request containing all cookies existing/stored of that request's domain. - GDPR (General Data Protection Regulation; 2018) and Cookie Law (ePrivacy Directive; 2002/2009)
- Persistent Cookies require consent notice;
- Session Cookies do not.
HTTP Request Header
- See
Network.HTTP.Headers
(set security flags:httpOnly
Prevent XSS; forbid any JS access. SameSite=strict
Prevent CSRF. secure=true
Via HTTPS
only.
Web API ::
document.cookie
Cookies are domain specific; sent by browser only to domain which wrote them.
With every request to a specific domain, the client's web browser looks to see if there is a cookie from that domain on the client's machine. If found, the browser will send the cookie with every request to that domain.
Cookie data limitations: if the data is hex (hash), okay to store raw, else base64-encode the raw string data.
window.btoa(raw) // ... btoa() is scope to Window OR GlobalWorker
Cookies :: Special Key Names
__Host-*
— Require HTTPS,Secure
, sansDomain
__Secure-*
— Require HTTPS,Secure
- Else cookie is not set.
JS Cookie Libraries
js-cookie
(1KB
); popular; simple API (get
,set
,remove
).Cookies.set(key, val, { path: '/', sameSite: 'strict' }
Minimal :: Get / Set ::
document.cookie
// Get function cookieGet(name) { var c = "; " + document.cookie; var x = c.split("; " + name + "="); if (x.length === 2) { return x.pop().split(";").shift(); } } // Set function cookieSet(name, value) { var expires = ""; var date = new Date(); date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString(); document.cookie = name + "=" + value + expires + "; path=/"; }
HTTP Caching ::
ETag
/If-Match
headers ( - Web Storage API includes two