Web Storage and IndexedDB
Local and Session Storage
Cookies; ~4 kB max, sent to server on every request. HTML5 storage supports ~5 MB max.
Storage is key-value string pairs accessible to JS on a specific origin (protocol + domain + port).
Two types of storage:
- Local storage: permanent data for site; key-value string pairs
- Session storage: cleared after end of session
IndexedDB
A indexed NoSQL DB:
- Multiple object stores
- Primary keys
- Indexes
- Asynchronous CRUD requests
CacheStorage
Accessible to service workers and hence requires HTTPS.
Stores pairs of request and response objects; for caching web resources.
Can be few hundred MBs.
self.addEventListener('install', event => {
event.waitUntil(
caches.open("my-cache").then(async cache => {
// Fetch, then add to cache
await cache.addAll(
[
'/css/bootstrap.css',
'/css/main.css',
'/js/bootstrap.min.js',
'/js/jquery.min.js',
'/offline.html'
]
);
// Shorthand for:
await cache.add(new Request("some-path"));
// Can also put arbitrary data into cache
await cache.add("some-path", new Response("some-data"))
})
);
});
self.addEventListener('fetch', event => event.respondWith(
caches.open("my-cache")
.then(cache => cache.match(event.request))
.then(response => {
if (response == undefined) {
// Not in cache
return fetch(event.request).then(response => {
// Response/request body can only be read once, so use `clone`
cache.put(event.request, response.clone());
return response;
});
}
return response;
})
)
);
Progressive Web Apps
Appear to be ‘installed’ like native apps: begin life in a browser tab and can be ‘installed’.
A PWA must:
- Originate from a secure origin
- Load while offline
- Reference a Web App Manifest: JSON file with properties such as name, start URL and icon
- Linked in the HTML page:
<link rel="manifest" href="./manifest.json">
- Linked in the HTML page:
It should:
- Act like an app; mobile friendly and fluid animations
- Load quickly: < 5s before service worker installed, < 2s after installation
Service Workers
Proxy ‘servers’ between the web app and network. Runs headless in its own thread, and must use HTTPS.
Service workers are used for notifications and background sync.
Service workers must be started by the web page:
if ("serviceWorker" in navigator) window.addEventListener("load", () => {
navigator.serviceWorker.register("./worker.js").then(registration => {
console.log(`Scope: ${registration.scope}`);
}).catch(err => console.error(err));
});
After installation, it can be in a few states:
- Activated
- Idle
- Terminated
- Fetch/message
Using service workers and CacheStorage:
const cacheName = "name";
const precacheResources = ["/", "/index.html", "/main.css"];
self.addEventListener("install", event => {
event.waitUntil(caches.open(cacheName)).then(cache => cache.addAll(precacheResources));
});
self.addEventListener("activate", () => console.log("Activated!"));
self.addEventListener("fetch", event => {
console.log(`Intercepting fetch to ${event.request.url}`);
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if (cachedResponse) return cachedResponse;
// Fallback to making a network request if not in cache
return fetch(event.request);
})
)
});
WebAssembly
Binary code that is pre-compiled to wasm bytecode - supported languages include C, C++ and Rust.
Ahead-of-time or just-in-time (interpreted) compilation of wasm.