Search code examples
workboxbackground-sync

Workbox 5.1.2 backgroundSync Queue configuration


I have recently migrated from Workbox 3.5.0 to Workbox 5.1.2

I am using Workbox SW via CDN

importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');

I have updated my service worker file to use the latest Plugin Classes and have renamed the classes appropriately - everything is working great!

The only real issue / confusion I am having is with the backgroundSync module. I have read through the documentation and have searched on Stackoverflow & Google for a solution / suggestion, but can't find anything that explicitly answers my question.

I am trying to add failed requests to a Queue that get retried once the network is restored.

workbox.routing.registerRoute(new RegExp('/\/php\/postPO.php/'),
  new workbox.strategies.NetworkOnly({
    plugins: [
      new workbox.backgroundSync.BackgroundSyncPlugin('po-data-queue', {
      maxRetentionTime: 24 * 60 * 2 
      })
    ]
  }),
 'POST'
);


const queue = new workbox.backgroundSync.Queue('po-data-queue-2');
self.addEventListener('fetch', (event) => {
  const promiseChain = fetch(event.request.clone()).catch((err) => {
    return queue.pushRequest({ request: event.request });
  });
event.waitUntil(promiseChain);
});

I know the above code doesn't work because if I give the 2 Queue names the same name then an error is thrown about using unique Queue names. Do I need both functions to use the backgroundSync module or is it one or the other. Also, do I need to create the indexedDB myself or does workbox handle this? When using workbox 3.5.0 I created the indexedDB and added failed requests like so (which worked fine):

function createIndexedDB() {
  if (!('indexedDB' in window)) {return null;}
  return idb.open('pos-data-queue', 1, function(upgradeDb) {
    if (!upgradeDb.objectStoreNames.contains('events')) {
      const eventsOS = upgradeDb.createObjectStore('events', {keyPath: 'key', autoIncrement: true});
    }
  });
}

const dbPromise = createIndexedDB();
function saveEventDataLocally(events) {
  console.log(events);
  if (!('indexedDB' in window)) {return null;}
  return dbPromise.then(db => {
    const tx = db.transaction('events', 'readwrite');
    const store = tx.objectStore('events');
    return Promise.all(events.map(event => store.put(event)))
   .catch((err) => {
    console.log(err);
    tx.abort();
    throw Error('Events were not added to the store');
   });
 });
}

const bgSyncPlugin = new workbox.backgroundSync.Plugin('pos-data-queue');
const networkWithBackgroundSync = new workbox.strategies.NetworkOnly({
  plugins: [bgSyncPlugin],
});

workbox.routing.registerRoute(
  /\/php\/postPO.php/,
  networkWithBackgroundSync,
 'POST'
);

I can't wrap my head around how this works, any help would be greatly appreciated


Solution

  • You are not required to use both BackgroundSyncPlugin and Queue. A unique name is required for each instance. The IndexedDB entries are managed by Workbox itself.

    In your code examples I see a suspicious space (making the regex invalid) when registering BackgroundSyncPlugin:

    workbox.routing.registerRoute(new RegExp(' /\/php\/postPO.php/'),
                                              ^
    

    Maybe you can try with:

    workbox.routing.registerRoute(/\/php\/postPO\.php/,
      new workbox.strategies.NetworkOnly({
        plugins: [
          new workbox.backgroundSync.BackgroundSyncPlugin('po-data-queue', {
            maxRetentionTime: 2 * 24 * 60 // two days
          })
        ]
      }),
     'POST'
    );
    

    The above will work for any URL that contains /php/postPO.php. You can test it here.

    The official docs here showcase some examples and how to test if the background sync is actually working.