patternjavascriptModerate
Service worker caching strategy: cache-first vs network-first vs stale-while-revalidate
Viewed 0 times
service workercache-firstnetwork-firststale-while-revalidateWorkboxPWAoffline
Problem
Developers apply a single caching strategy to all resources in a service worker. Cache-first for API data returns stale JSON; network-first for static assets defeats the purpose of caching.
Solution
Match strategy to resource type:
// Workbox (recommended abstraction)
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
// Static assets: cache-first (hashed filenames change on update)
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({ cacheName: 'images', plugins: [new ExpirationPlugin({ maxEntries: 50 })] })
);
// API data: network-first (freshness matters, cache as fallback)
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({ cacheName: 'api-responses', networkTimeoutSeconds: 3 })
);
// Non-critical assets: stale-while-revalidate (serve fast, update in background)
registerRoute(
({ request }) => request.destination === 'script',
new StaleWhileRevalidate({ cacheName: 'scripts' })
);
// Workbox (recommended abstraction)
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
// Static assets: cache-first (hashed filenames change on update)
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({ cacheName: 'images', plugins: [new ExpirationPlugin({ maxEntries: 50 })] })
);
// API data: network-first (freshness matters, cache as fallback)
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({ cacheName: 'api-responses', networkTimeoutSeconds: 3 })
);
// Non-critical assets: stale-while-revalidate (serve fast, update in background)
registerRoute(
({ request }) => request.destination === 'script',
new StaleWhileRevalidate({ cacheName: 'scripts' })
);
Why
Cache-first maximizes speed but serves stale data. Network-first maximizes freshness but loses offline capability. Stale-while-revalidate balances both for resources where occasional staleness is acceptable.
Gotchas
- Service workers only intercept HTTPS requests (plus localhost)
- Updating a service worker requires the old one to be fully unloaded first — use skipWaiting() and clients.claim() carefully
- Cache size is not unlimited — implement ExpirationPlugin with maxEntries or maxAgeSeconds
- Opaque responses (no-cors cross-origin) pad cache size to 7MB each — avoid caching them
Code Snippets
Workbox precaching for the app shell
// Precache app shell files at install time
import { precacheAndRoute } from 'workbox-precaching';
precacheAndRoute(self.__WB_MANIFEST); // injected by workbox-webpack-pluginContext
When implementing offline support or improving repeat-visit performance with a service worker
Revisions (0)
No revisions yet.