Concept
Choosing the Right Caching Strategy
Using a Service Worker, you customize how the browser resolves assets dynamically based on their category:
// CACHE-FIRST (Safe for static assets like images/fonts)event.respondWith(caches.match(req).then(res => res || fetch(req)));
Cache-First checks Cache Storage first. If the file exists, it returns it instantly. The network is only queried as a fallback if the file is absent. Highly efficient for static files.
- Cache-First (Cache Falling Back to Network):
- Logic: Check cache first. If found, return instantly. Otherwise, fetch from network and save to cache.
- Best for: Static, non-changing assets (images, fonts, vendor stylesheets).
- Network-First (Network Falling Back to Cache):
- Logic: Try network first. If successful, return and save to cache. If connection fails (offline), fall back to cache.
- Best for: Time-sensitive data that updates frequently (user inbox, dashboard feeds).
- Stale-While-Revalidate (SWR):
- Logic: Return the cached resource instantly, while triggering a background fetch to update the cache for the next reload.
- Best for: Content that updates occasionally but benefits from instant loads (user profiles, navigation paths).
Common Mistakes
1. Applying Cache-First to dynamic API JSON requests
Using Cache-First on endpoints like /api/user-status blocks users from seeing updates because the browser always serves the cached version, ignoring database shifts. Use Network-First or SWR instead.
2. Not cleaning up obsolete cache keys on activate events
As you update files, cache stores build up old versions. If you do not clear obsolete caches, users' disk storage fills up and browsers serve legacy styles. Use a unique cache name and delete old keys:
const CACHE_NAME = 'app-v2';
self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys().then(keys => Promise.all(
keys.map(k => k !== CACHE_NAME && caches.delete(k))
))
);
});Best Practices
- Match Strategies to File Types: Use Cache-First for static assets, Network-First for dynamic APIs, and SWR for structural frameworks.
- Implement Workbox: Use Google's Workbox library to build caching strategies declaratively:
import { registerRoute } from 'workbox-routing'; import { StaleWhileRevalidate } from 'workbox-strategies'; registerRoute(({ request }) => request.destination === 'script', new StaleWhileRevalidate()); - Configure Fallback Pages: Cache a generic
/offline.htmlfile during installation to render if the user goes offline and requests an uncached page.
