How to Cache SVG Requests with Service Workers
This article explains how service workers intercept and cache Scalable Vector Graphics (SVG) requests to ensure graphical assets remain accessible in offline web applications. You will learn how to register a service worker, pre-cache critical SVG icons, intercept network requests through fetch events, and apply effective caching strategies such as Cache-First to deliver optimal offline performance.
1. Registering the Service Worker
To intercept any network requests, including SVGs, you must first register a service worker in your main application script.
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then((registration) => {
console.log('Service Worker registered:', registration.scope);
})
.catch((error) => {
console.error('Service Worker registration failed:', error);
});
});
}2. Precaching Static SVGs on Install
For core UI icons, logos, and illustrations that rarely change,
precache them during the service worker’s install lifecycle
event.
const CACHE_NAME = 'svg-cache-v1';
const STATIC_SVGS = [
'/icons/logo.svg',
'/icons/menu.svg',
'/icons/user.svg'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(STATIC_SVGS);
})
);
self.skipWaiting();
});3. Intercepting and Caching SVG Network Requests
When an HTML document requests an SVG file via an
<img> tag, CSS background-image,
<object>, or JavaScript fetch(), the
service worker intercepts the request through the fetch
event.
Cache-First Strategy for SVGs
A Cache-First strategy is ideal for vector assets because they are usually static. The service worker checks the Cache Storage API first. If the file exists, it returns the cached SVG immediately. If not, it fetches it over the network, stores a clone in the cache for future offline use, and delivers the response to the browser.
self.addEventListener('fetch', (event) => {
const requestUrl = new URL(event.request.url);
// Check if the requested file is an SVG
if (requestUrl.pathname.endsWith('.svg')) {
event.respondWith(
caches.open(CACHE_NAME).then(async (cache) => {
const cachedResponse = await cache.match(event.request);
if (cachedResponse) {
return cachedResponse;
}
try {
const networkResponse = await fetch(event.request);
// Ensure valid response before caching
if (networkResponse && networkResponse.status === 200) {
cache.put(event.request, networkResponse.clone());
}
return networkResponse;
} catch (error) {
// Provide an optional fallback SVG if offline and not in cache
return cache.match('/icons/offline-placeholder.svg');
}
})
);
}
});4. Cache Maintenance and Invalidation
When updating SVGs, update the cache version name (e.g.,
svg-cache-v2). Use the activate event to
remove outdated caches.
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => caches.delete(name))
);
})
);
self.clients.claim();
});Important Considerations
- Inline SVGs: SVGs embedded directly within HTML
markup (
<svg>...</svg>) cannot be intercepted individually via the fetch event. They are cached as part of the host HTML page. - Cross-Origin SVGs: If you load SVGs from an
external CDN, ensure the CDN sends appropriate Cross-Origin Resource
Sharing (CORS) headers if you plan to inspect the response before
caching. Use
mode: 'cors'when fetching programmatically.