Cache Client Side Data
Vaadin caches the client-side views out-of-the-box, but not the client-side data. This may lead to the situation that even the client-side view is available offline, it’s not very useful since there is no data. To overcome this, you can use localStorage to store the client-side data, so that the data available even offline.
A Cacheable Wrapper With Local Storage
Assume you have a function to retrieve the data from the backend.
After the data is retrieved, you can save it into localStorage as a key-value pair.
It is also good to provide a default value, in case the data is neither available from the backend nor cache.
Example: define a cacheable helper in cacheable.ts for caching client-side data.
export async function cacheable<T>(fn: () => Promise<T>, key: string, defaultValue: T) {
let result;
try {
// retrieve the data from backend.
result = await fn();
// save the data to localStorage.
localStorage.setItem(key, JSON.stringify(result));
} catch {
// if failed to retrieve the data from backend, try localStorage.
const cached = localStorage.getItem(key);
// use the cached data if available, otherwise the default value.
result = cached ? JSON.parse(cached) : defaultValue;
}
return result;
}Now you can use the cacheable wrapper in your client-side view.
Example: use the cacheable wrapper.
// import the cacheable function from the path to cacheable.ts file (without the suffix)
import { cacheable } from 'path-to-cacheable';
// instead of always relying on the backend to retrieve the data. e.g.
// const stats = await getStats();
// you can now wrap getStats into the cacheable helper.
const stats = await cacheable(() => getStats(), 'stats', {});Clear the Local Storage
It is a good practice to clear the data stored in the localStorage, for example, when a user logs out.
Suppose there is a logout event, the above cacheable wrapper could be improved as
// the name of the cache for offline usage
const CACHE_NAME = 'offline-cache';
window.addEventListener('logout', () => {
// clear the data from localStorage when a user logs out
clearCache();
});
export async function cacheable<T>(fn: () => Promise<T>, key: string, defaultValue: T) {
let result;
try {
// retrieve the data from backend.
result = await fn();
// save the data to localStorage.
const cache = getCache();
cache[key] = result;
localStorage.setItem(CACHE_NAME, JSON.stringify(cache));
} catch {
// if failed to retrieve the data from backend, try localStorage.
const cache = getCache();
const cached = cache[key];
// use the cached data if available, otherwise the default value.
result = cached === undefined ? defaultValue : cached;
}
return result;
}
function getCache(): any {
const cache = localStorage.getItem(CACHE_NAME) || '{}';
return JSON.parse(cache);
}
function clearCache() {
localStorage.removeItem(CACHE_NAME);
}