This page contains a set of example caching strategies you can use with Workbox.
Google Fonts
The Google Fonts service consists of two parts:
- The stylesheet with the
@font-face
definitions, which link to the font files. - The static, revisioned font files.
The stylesheet can change frequently, so it's best to use a caching strategy like stale while revalidate that checks for updates with every request. The font files themselves, on the other hand, do not change and can leverage a cache first strategy.
Here we've limited the age of the cached font files to one year (matching the
HTTP Cache-Control
header) and the max entries to 30 (to ensure we don't use
up too much storage on the user's device).
import {registerRoute} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {ExpirationPlugin} from 'workbox-expiration';
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
registerRoute(
({url}) => url.origin === 'https://fonts.googleapis.com',
new StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets',
})
);
// Cache the underlying font files with a cache-first strategy for 1 year.
registerRoute(
({url}) => url.origin === 'https://fonts.gstatic.com',
new CacheFirst({
cacheName: 'google-fonts-webfonts',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 365,
maxEntries: 30,
}),
],
})
);
Caching Images
You might want to use a cache-first strategy for images, by matching against the intended destination of the request.
import {registerRoute} from 'workbox-routing';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
})
);
Cache CSS and JavaScript Files
You might want to use a stale-while-revalidate strategy for CSS and JavaScript files that aren't precached, by matching against the destination of the incoming request.
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(
({request}) => request.destination === 'script' ||
request.destination === 'style',
new StaleWhileRevalidate({
cacheName: 'static-resources',
})
);
Caching Content from Multiple Origins
You can create regular expressions to cache similar requests from multiple
origins in a single route by combining multiple checks into a single
matchCallback
function.
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(
({url}) => url.origin === 'https://fonts.googleapis.com' ||
url.origin === 'https://fonts.gstatic.com',
new StaleWhileRevalidate(),
);
Restrict Caches for a Specific Origin
You can cache assets for a specific origin and apply expiration rules on that cache. For example, the example below caches up to 50 requests for up to 5 minutes.
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({url}) => url.origin === 'https://hacker-news.firebaseio.com',
new CacheFirst({
cacheName: 'stories',
plugins: [
new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 5 * 60, // 5 minutes
}),
new CacheableResponsePlugin({
statuses: [0, 200],
}),
],
})
);
Force a Timeout on Network Requests
There may be network requests that would be beneficial if they were served from the network, but could benefit by being served by the cache if the network request is taking too long.
For this, you can use a NetworkFirst
strategy with the
networkTimeoutSeconds
option configured.
import {registerRoute} from 'workbox-routing';
import {NetworkFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
({url}) => url.origin === 'https://hacker-news.firebaseio.com',
new NetworkFirst({
networkTimeoutSeconds: 3,
cacheName: 'stories',
plugins: [
new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 5 * 60, // 5 minutes
}),
],
})
);
Cache Resources from a Specific Subdirectory
You can route requests to files in a specific directory on your local web app by checking the
origin
and pathname
properties of the
URL object passed to the
matchCallback
function:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(
({url}) => url.origin === self.location.origin &&
url.pathname.startsWith('/static/'),
new StaleWhileRevalidate()
);
Cache Resources Based on Resource Type
You can use the
RequestDestination
enumerate type of the
destination
of the request to determine a strategy.
For example, when the target is <audio>
data:
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
registerRoute(
// Custom `matchCallback` function
({request}) => request.destination === 'audio',
new CacheFirst({
cacheName: 'audio',
plugins: [
new ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
})
);
Access Caches from Your Web App's Code
The Cache Storage
API is available
for use in both service worker and in the context of window
clients. If you
want to make changes to caches—add or remove entries, or get a list of cached
URLs—from the context of your web app, you can do so directly, without having to
communicate with the service worker via postMessage()
.
For instance, if you wanted to add a URL to the a given cache in response to a user action in your web app, you can use code like the following:
// Inside app.js:
async function addToCache(urls) {
const myCache = await window.caches.open('my-cache');
await myCache.addAll(urls);
}
// Call addToCache whenever you'd like. E.g. to add to cache after a page load:
window.addEventListener('load', () => {
// ...determine the list of related URLs for the current page...
addToCache(['/static/relatedUrl1', '/static/relatedUrl2']);
});
The cache name, 'my-cache'
, can then be referred to when setting up a route in
your service worker, and that route can take advantage of any cache entries
that were added by the web page itself:
// Inside service-worker.js:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(
({url}) => url.origin === self.location.origin &&
url.pathname.startsWith('/static/'),
new StaleWhileRevalidate({
cacheName: 'my-cache', // Use the same cache name as before.
})
);