Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Workbox setDefaultHandler

I'm switching from sw-toolbox to Workbox and I can't figure out how to use setDefaultHandler().

If I try (as stated in the documentation linked above):

workboxSW.router.setDefaultHandler({
    handler: new workbox.runtimeCaching.CacheFirst()
});

I get an error that runtimeCaching is undefined:

Uncaught ReferenceError: router is not defined

So.. how do I use it and configure it in a way similar to how I could configure sw-toolbox:

toolbox.options.cache = {
    name: "default",
    maxEntries: 128,
    maxAgeSeconds: (60*60*24), // 24hrs
};
toolbox.router.default = toolbox.cacheFirst;

I would like to be able to do something like this:

workboxSW.router.setDefaultHandler({
    handler: workboxSW.strategies.cacheFirst({
        cacheName: 'default',
        cacheExpiration: {
            maxEntries: 128,
        },
        cacheableResponse: {statuses: [0, 200]},
    })
});

..which doesn't throw compile errors but when I use it I get this:

Uncaught (in promise) TypeError: Request method 'POST' is unsupported

..and my Cache Storage for 'default' remains empty..?

like image 222
REJH Avatar asked Jan 29 '23 20:01

REJH


2 Answers

Since my edits for Jeff's first solution were rejected I'll just go ahead and submit an answer myself.

Jeff's sample came close. He suggested:

You could check for the request type in the default handler, and only apply the cache-first strategy to GET requests:

workboxSW.router.setDefaultHandler({
  handler: (args) => {
    if (args.event.request.method === 'GET') {
      return workboxSW.strategies.cacheFirst(args);
    }
    return fetch(args.event.request);
  },
});

It's the right approach but the example code he provided didn't work. The handler argument needs a handler, not a strategy. Luckily, strategies have exactly one (public) method, called "handle".

So I modified his code a little; First, I create a strategy called defaultStrategy with all the options I need. Then, in the setDefaultHandler call, I return defaultStrategy.handle(args) instead of the CacheFirst constructor. That's it!

// Register 'default'
var defaultStrategy = workboxSW.strategies.cacheFirst({
    cacheName: "default",
    cacheExpiration: {
        maxEntries: 128,
        // more options..
    },
    cacheableResponse: {statuses: [0, 200]},
});
workboxSW.router.setDefaultHandler({
    handler: (args) => {
        if (args.event.request.method === 'GET') {
            return defaultStrategy.handle(args);
        }
        return fetch(args.event.request);
    },
});

UPDATE: Workbox v3

As I pointed out in the comments below, the above code doesn't work with Workbox v3. Use this instead:

// Register 'default'
var defaultStrategy = workbox.strategies.cacheFirst ({
    cacheName: "your.cache.name",
    plugins: [
        new workbox.expiration.Plugin({
            maxEntries: 128,
            maxAgeSeconds: 7 * 24 * 60 * 60, // 1 week
            purgeOnQuotaError: true, // Opt-in to automatic cleanup
        }),
        new workbox.cacheableResponse.Plugin({
            statuses: [0, 200] // for opague requests
        }),
    ],
});
workbox.routing.setDefaultHandler(
    (args) => {
        if (args.event.request.method === 'GET') {
            return defaultStrategy.handle(args); // use default strategy
        }
        return fetch(args.event.request);
    }
);
like image 108
REJH Avatar answered May 04 '23 11:05

REJH


workboxSW.router.setDefaultHandler({
  handler: workboxSW.strategies.cacheFirst({...})
});

is the right syntax in general.

I believe that you're seeing

Uncaught (in promise) TypeError: Request method 'POST' is unsupported

because the default handler is triggered for all HTTP requests that don't match any explicit route, including HTTP POST requests. But a HTTP POST request can't be used with the Cache Storage API, and an exception similar to what you're seeing will be thrown when the cache-first strategy attempts to store the request/response pair in the cache.

In this particular case, when you know that your web app is going to make HTTP POST requests, you could take one of two approaches.

You could check for the request type in the default handler, and only apply the cache-first strategy to GET requests:

workboxSW.router.setDefaultHandler({
  handler: (args) => {
    if (args.event.request.method === 'GET') {
      return workboxSW.strategies.cacheFirst(args);
    }
    return fetch(args.event.request);
  },
});

Alternatively, you could create a wildcard route that matches all requests, and take advantage of the fact that by default, routes will only match HTTP GET:

workboxSW.router.registerRoute(
  /./, // This should match all requests.
  workboxSW.strategies.cacheFirst({...}),
  'GET' // This is the default, and can be left out.
);
like image 43
Jeff Posnick Avatar answered May 04 '23 11:05

Jeff Posnick