963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
1.6 KiB
1.6 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Cache Storage API Calls | LOW-MEDIUM | reduces expensive I/O | javascript, localStorage, storage, caching, performance |
Cache Storage API Calls
localStorage, sessionStorage, and document.cookie are synchronous and expensive. Cache reads in memory.
Incorrect (reads storage on every call):
function getTheme() {
return localStorage.getItem('theme') ?? 'light';
}
// Called 10 times = 10 storage reads
Correct (Map cache):
const storageCache = new Map<string, string | null>();
function getLocalStorage(key: string) {
if (!storageCache.has(key)) {
storageCache.set(key, localStorage.getItem(key));
}
return storageCache.get(key);
}
function setLocalStorage(key: string, value: string) {
localStorage.setItem(key, value);
storageCache.set(key, value); // keep cache in sync
}
Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
Cookie caching:
let cookieCache: Record<string, string> | null = null;
function getCookie(name: string) {
if (!cookieCache) {
cookieCache = Object.fromEntries(document.cookie.split('; ').map((c) => c.split('=')));
}
return cookieCache[name];
}
Important (invalidate on external changes):
If storage can change externally (another tab, server-set cookies), invalidate cache:
window.addEventListener('storage', (e) => {
if (e.key) storageCache.delete(e.key);
});
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
storageCache.clear();
}
});