Easy Background Sync with Workbox

Hello everyone! Welcome to the first short post on my new blog “On the web with Justin”. I will be aiming to post atleast one article a week as I begin this blog journey and may increase that in the future. I will be posting on topics such as the latest web tech, Progressive Web Apps, Service Workers, Web Components and more. With this out of the way lets dive straight into todays content!

Mobile networks are not known for being reliable and in todays fast paced world this is not ideal. We may come up with that perfect tweet to post, pull out our phone and discover that boom, we dont currently have any service. Native apps typically handle this very nicely by allowing the action the user tried to complete while they were offline to be automatically retried once the user is back online but, web apps have typically not been able to achive this functionality, until now!

What is Workbox?

In todays post we will be making use of Workbox, a library built to make service workers easy. While I will not be diving into deep detail about what Workbox is you can check out the Workbox docs for more info. Because of this, todays post is going to be assuming basic knowledge of Workbox.

What is background sync?

The Background Sync API that powers this functionality is one of the awesome features that Service Workers have given us. The Background Sync API enables you to “catch” requests that the user tries to make while offline and replay those actions once the user is back online.

What are use cases for this you might be asking? One common use case that apps such as the Facebook app use is allowing the user to make posts offline and then actually post those posts once the user is back online. With the Background Sync API you can enable this same type of functionality in your PWA! Lest dive into how we can use the Background Sync API in Workbox.

Alright, lets do this!

We first need to decide what actions we would like for the user to be able to do while offline. Deciding this should be a part of deciding what your offline strategy is, a topic that we will dive deeper into in a future post. For this example lets say we have are going to enable the user to post to a feed while offline. The url this action makes a POST request too is https://my-api-server/post. With this knowledge we can now start using the Background Sync API!

We first need to register a route with workbox to handle this URL. We can accomplish this with the below bit of JavaScript in our service worker file:

1
2
3
4
5
workbox.routing.registerRoute(
new RegExp('^https:\/\/my-api-server/post\/'),
workbox.strategies.networkOnly(),
'POST'
)

This snippet registers a route (we are using a RegExp route in this case) which will match the URL our action is making a request too. We then say that we want to use the networkOnly strategy on this route. You can read up more on strategies here in the Workbox docs, but the basics of the networkOnly strategy is that it will never look to the cache for this route, but instead will always go to the network. We then finally say that we want to handle all ‘POST’ requests to this url.

We now need to set up our instance of the Workbox backgroundSync plugin. Lets do this with the following snippet of code in our service worker file:

1
2
3
const bgSyncPlugin = new workbox.backgroundSync.Plugin('myQueueName', {
maxRetentionTime: 24 * 60 // Retry for max of 24 Hours
});

We now have an instance of the Workbox backgroundSync plugin we can use in the route we registered earlier. Lets pass this instance of the plugin to our route handler:

1
2
3
4
5
6
7
workbox.routing.registerRoute(
new RegExp('^https:\/\/my-api-server/post\/'),
workbox.strategies.networkOnly({
plugins: [bgSyncPlugin]
}),
'POST'
)

With this bit of code our Background Sync plugin will now handle all requests that match our route! Any failed ‘POST’ requests to this route will now be saved by our service worker and replayed once the user is back online!

The final coat of Polish

The above code is technically all the code needed to enable the Background Sync API on a route with Workbox, but lets take this one step further. Normally most apps will display a notification once an action has been replayed and, we can do the same in our PWA!

Lets first write a function to handle showing a notification:

1
2
3
4
5
6
7
const showNotification = () => {
self.registration.showNotification('Post Sent', {
body: 'You are back online and your post was successfully sent!',
icon: 'assets/icon/256.png',
badge: 'assets/icon/32png.png'
});
};

Note: you will need to set up web push notifications first to be able to show a notification to the user. This is something we will dive into in a future post but for now I recommend checking out this tutorial on setting them up *
Now all we need to do is call our showNotification function we wrote above once the queued actions have been replayed by the service worker. Lets change our background sync plugin implementation to accomplish this:

1
2
3
4
5
6
7
8
const bgSyncPlugin = new workbox.backgroundSync.Plugin('myQueueName', {
maxRetentionTime: 24 * 60 // Retry for max of 24 Hours,

// the new bit
callbacks: {
queueDidReplay: showNotification
}
});

With that final snippet we will now display a notification to the user once an action has successfully been completed, awesome!

For more examples check out my implementation in my Cannabis social network PWA I am currently building (more on that in a future post).

For more info on Background Sync in Workbox check out these docs.