Offline Caching Strategies: CacheFirst NetworkFirst
Implement Cache-First for static assets and Network-First for API responses using the Cache API and the Workbox library.
Offline Caching Strategies: CacheFirst NetworkFirst is a free Frontend Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Caching Strategies Matter
Service workers can intercept every fetch — but you need a strategy. Different content needs different rules: a logo should be cached forever, an API response should always be fresh, news articles benefit from stale-while-revalidate.
The Cache API
Service workers use the Cache API: a key-value store of Request → Response pairs, scoped per origin. Persisted across sessions.
// open a cache:
const cache = await caches.open('v1');
// add resources:
await cache.add('/styles.css');
await cache.addAll(['/', '/app.js', '/styles.css']);
// look up:
const response = await cache.match('/styles.css');
// delete:
await cache.delete('/styles.css');Cache First
Check the cache first. If found, return it. If not, fall back to network and cache the response. Best for: static assets, fonts, logos, app shell.
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then(cached => {
if (cached) return cached;
return fetch(event.request).then(res => {
const clone = res.clone();
caches.open('v1').then(c => c.put(event.request, clone));
return res;
});
})
);
});Network First
Try network first. If it fails (offline), fall back to cache. Best for: API calls, dynamic content where freshness matters more than speed.
self.addEventListener('fetch', (event) => {
event.respondWith(
fetch(event.request).then(res => {
const clone = res.clone();
caches.open('api-v1').then(c => c.put(event.request, clone));
return res;
}).catch(() => caches.match(event.request))
);
});Stale While Revalidate
Return cache immediately (fast), then fetch in the background and update the cache for next time. Best for: avatars, news articles, semi-fresh data.
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then(cached => {
const network = fetch(event.request).then(res => {
caches.open('v1').then(c => c.put(event.request, res.clone()));
return res;
});
return cached || network;
})
);
});Network Only
Bypass the cache entirely — always go to network. Use for non-cacheable requests (auth endpoints, analytics, mutations).
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api/auth')) {
event.respondWith(fetch(event.request));
return;
}
// ... other strategies
});Cache Only
Never go to network — return cache or fail. Useful for files you precached and never want to refresh during a session.
Workbox Strategies
Workbox bundles all strategies as named classes. Less boilerplate.
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
registerRoute(({ request }) => request.destination === 'image',
new CacheFirst({ cacheName: 'images' })
);
registerRoute(({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({ cacheName: 'api', networkTimeoutSeconds: 3 })
);
registerRoute(({ request }) => request.destination === 'document',
new StaleWhileRevalidate({ cacheName: 'pages' })
);Cache Expiration
Caches grow forever unless you set limits. Workbox provides ExpirationPlugin.
import { ExpirationPlugin } from 'workbox-expiration';
new CacheFirst({
cacheName: 'images',
plugins: [new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 30 * 24 * 60 * 60 // 30 days
})]
});Cacheable Response
By default, browsers cache only 200 responses. Skip 4xx, 5xx, and opaque (cross-origin no-cors) responses to avoid filling the cache with errors.
Offline Fallback Page
Show a friendly offline page when a navigation fails — better UX than the browser's default error.
self.addEventListener('install', (e) => {
e.waitUntil(caches.open('offline').then(c => c.add('/offline.html')));
});
self.addEventListener('fetch', (e) => {
if (e.request.mode === 'navigate') {
e.respondWith(
fetch(e.request).catch(() => caches.match('/offline.html'))
);
}
});Choosing the Right Strategy
Static assets (logo, font, CSS): Cache First. API data (user profile, feed): Network First. Sometimes-fresh content (avatars, news): Stale While Revalidate. Authentication: Network Only. Pre-installed static files: Cache Only.
Quick Check
Which caching strategy is best for a CSS file that rarely changes but must load fast?
Recap: Caching Strategies
Cache First: static assets (fastest, may be stale). Network First: API data (freshest, slower). Stale While Revalidate: serve cache + fetch in background. Network Only: auth/mutations. Cache Only: pre-installed shell. Use Workbox for less boilerplate. Set expiration limits. Add an offline fallback page. Pick per resource type.
Frequently asked questions
Is the “Offline Caching Strategies: CacheFirst NetworkFirst” lesson free?
Yes — the full text of “Offline Caching Strategies: CacheFirst NetworkFirst” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.
What will I learn in “Offline Caching Strategies: CacheFirst NetworkFirst”?
Implement Cache-First for static assets and Network-First for API responses using the Cache API and the Workbox library. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Frontend Academy?
No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Offline Caching Strategies: CacheFirst NetworkFirst” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Frontend Academy lesson?
Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Web App Manifest
- Service Worker Registration and Lifecycle
- Offline Caching Strategies: CacheFirst NetworkFirst
- Push Notifications