I have a web application that wants to cache recently-referenced images to support offline use. The images are not expected to ever change, so I have configured my Workbox-based service worker to use the CacheFirst strategy for all requests from the image server:
//service-worker.js
self.skipWaiting();
clientsClaim();
cleanupOutdatedCaches();
registerRoute(
({ request }) => request.url.startsWith('https://example.com'),
new CacheFirst({
cacheName: 'images',
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
new ExpirationPlugin({
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
maxEntries: 100,
}),
],
})
);
When my application runs, I can see in Chrome developer tools Network tab that the service worker is successfully serving these images after the initial load:
So far so good. But then, there is another request in the Network tab that indicates that the service worker itself is fetching the image from the network (here, satisified by the browser's disk cache):
My understanding of CacheFirst is that the service worker should not make a network request at all if the cache satisfies the request. What is causing this behavior?
While debugging, I had missed this message from Workbox in the Chrome developer tools:
The request for '/service-worker.js' returned a response that does not meet the criteria for being cached.
This led me to find information about opaque responses, and some helpful information describing third-party requests, which allowed me to fix this in my environment using the crossorigin attribute in <img>
tags:
<img :src="imagePath"
crossorigin="anonymous"
/>
In retrospect, another clue that the original images weren't being cached at all (even though they were being satisified by the service worker) was that the Cache Storage explorer in Chrome developer tools showed only the workbox precache (and not my "images" cache that would hold these cached images):