I am looking for the way to modify the response outside of workbox library! Is there any example to achive this?
Thanks!
@jecky011 could you provide a little more context about what you are trying to do / would like to do?
I am possibly interested in something like this, but for requests.
I am using the cache-first strategy, but I don't like how I can't read the status code of opaque responses, thus may end up caching a 404/500/etc (the objects in that cache are versioned, so are cached forever). It would be brilliant if I was able to CORS-ify requests before they went out (but still use a predefined caching strategy with all its wondrous features).
I understand that there is the <img crossorigin /> attribute, but there is no equivalent I'm aware of for background-image: url(...), and seeing as this is entirely specific to service worker caching I'd rather have the logic in there, rather than in the HTML.
@diachedelic What you describe is doable, with a bit of additional work.
You can write a custom handlerCallback to implement the logic for intercepting and responding to the outgoing request, and make use of the RequestWrapper class (or just use the Fetch and Cache Storage APIs directory) from within your handler.
const customRequestWrapper = new workbox.runtimeCaching.RequestWrapper({
cacheName: 'background-images',
plugins: [], // As needed for, e.g., cache expiration.
});
const customHandler = async ({event, url}) => {
const request = new Request(url, {mode: 'cors'});
const cachedResponse = await customRequestWrapper.match({request});
return cachedResponse || customRequestWrapper.fetchAndCache({request});
};
workboxSW.router.registerRoute(
new RegExp('^https://third-party-domain.com/background-images/'),
customHandler
);
Thanks, that works great. I changed new Request(url, {mode: 'cors'}) to new Request(event.request, { mode: 'cors' }), thereby (hopefully) only altering the mode of the request and leaving other stuff (headers etc) unchanged.
Now I am upgrading to workbox v3, and I'm not sure if workbox-runtime-caching's RequestWrapper can still be used with the rest of the codebase (seeing as workbox-runtime-caching is still v2). Things seem to be working but I get this error every so often:
Uncaught (in promise) WorkboxError: The parameter 'request' passed into 'workbox-cache-expiration.Plugin.cacheDidUpdate()' must be an instance of class Request.
at Object.isInstance (https://com09/service-worker.js:143:11)
at Plugin.cacheDidUpdate (https://com09/service-worker.js:6322:87)
at https://com09/service-worker.js:5712:2957
at Generator.next (<anonymous>)
at step (https://com09/service-worker.js:5689:30)
at https://com09/service-worker.js:5700:13
Relevant code:
...
import router from 'workbox-routing'
import { RequestWrapper } from 'workbox-runtime-caching'
import { Plugin as CacheExpirationPlugin } from 'workbox-cache-expiration'
...
const wrapper = new RequestWrapper({
cacheName: collection,
plugins: [
new CacheExpirationPlugin({
maxEntries: 100, // leave space for JSON API responses
maxAgeSeconds: 60 * 60 * 24 * 7, // one week
}),
],
})
const handler = async ({ event }) => {
const request = new Request(event.request, {
// transform request to CORS, thereby avoiding an opaque response with a
// status code of 0
// see https://github.com/GoogleChrome/workbox/issues/938
mode: 'cors',
// credentials break Access-Control-Allow-Origin: *
// see // https://stackoverflow.com/questions/34078676/access-control-allow-origin-not-allowed-when-credentials-flag-is-true-but#answer-34099399
credentials: 'omit',
})
const cachedResponse = await wrapper.match({ request })
return cachedResponse || wrapper.fetchAndCache({ request })
}
router.registerRoute(
({ url }) => url.origin === baseURL,
handler,
)
...
Regarding the WorkboxError, the request argument appears to be undefined in Chrome's debugger.
I wouldn't try to mix RequestWrapper from v2 with code from v3.
The rough equivalent in v3 would be something like:
const cacheName = 'collection';
const strategy = workbox.strategies.networkFirst({
cacheName,
plugins: [
new workbox.expiration.Plugin({
maxEntries: 100,
maxAgeSeconds: 60 * 60 * 24 *7,
})
],
});
const handler = async ({event}) => {
const request = new Request(event.request, {
mode: 'cors',
credentials: 'omit',
});
const cachedResponse = await caches.match(request, {
cacheName,
});
return cachedResponse || strategy.makeRequest({
event,
request,
});
}
Thanks a bunch, that works perfectly, no errors!
Most helpful comment
I wouldn't try to mix
RequestWrapperfrom v2 with code from v3.The rough equivalent in v3 would be something like: