5

I am using workbox v4.3.1 to provide offline capability to the users of the web application.

While everything works perfectly in Chrome as you would expect a PWA to work (i.e everything is cached locally, all the updates from the APP are captured in IndexedDB and synced back to the server when the application is back online.

However the major use case for me is to provide support for iOS Safari and as a PWA.

While all the pages are cached locally using the Service Worker in Safari and all the offline updates are also captured in the indexed DB as shown below,

enter image description here

However, when the connection returns online, the sync event is not triggered by the browser (Safari in this case). While background sync is not supported natively by Safari, I would expect that when I refresh the page, SW initialisation should trigger the sync event manually if it finds some data to be refreshed to the server in the indexed DB.

But this is not happening and I tried to manually listen for the "message" - "replayRequests" and then replay the requests - that did not work as well.

Any help here would be appreciated. Here is the service worker code for reference.

// If we're not in the context of a Web Worker, then don't do anything if ("function" === typeof importScripts) { importScripts( "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js" ); //Plugins // Background Sync Plugin. const bgSyncPlugin = new workbox.backgroundSync.Plugin("offlineSyncQueue", { maxRetentionTime: 24 * 60 }); // Alternate method for creating a queue and managing the events ourselves. const queue = new workbox.backgroundSync.Queue("offlineSyncQueue"); workbox.routing.registerRoute( matchCb, workbox.strategies.networkOnly({ plugins: [ { fetchDidFail: async ({ request }) => { await queue.addRequest(request); } } ] }), "POST" ); // CacheKeyControlPlugin const myCacheKeyPlugin = { cacheKeyWillBeUsed: async ({ request, mode }) => { normalizedUrl = removeTimeParam(request.url); return new Request(normalizedUrl); } }; if (workbox) { console.info("SW - Workbox is available and successfully installed"); } else { console.info("SW - Workbox unavailable"); } //Intercept all api requests var matchCb = ({ url, event }) => { // Filter out the presence api calls return url.pathname.indexOf("somethingidontwanttocache") == -1; }; function removeTimeParam(urlString) { let url = new URL(urlString); url.searchParams.delete("time"); return url.toString(); } /* //Pre cache a page and see if it works offline - Temp code workbox.precaching.precache(getPageAPIRequestURLs(), { cleanUrls: false }); */ workbox.routing.registerRoute( matchCb, new workbox.strategies.CacheFirst({ cacheName: "application-cache", plugins: [myCacheKeyPlugin] }) ); self.addEventListener("message", event => { if (event.data === "replayRequests") { queue.replayRequests(); } }); } 

1 Answer 1

4

workbox-background-sync emulates background sync functionality in browsers that lack native support by replaying queued requests whenever the service worker process starts up. The service worker process is meant to be lightweight and short lived, and is killed aggressively when there's a period of time without any events, and then is started up again in response to further events.

Reloading a web page may cause the service worker process to start up, assuming it had previously been stopped. But if the service worker is still running, then reloading the page will just cause a fetch event to be fired on the existing process.

The interval at which a service worker process can remain idle before it's killed is browser-dependent.

Chrome's DevTools offers a method of inspecting the state of a service worker and starting/stopping it on demand, but I don't believe Safari's DevTools offers that functionality. If you wanted to guanratee that a service worker was stopped and then start it up again, I would quit Safari, reopen it, and then navigate back to your web app.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Jeff, Thank you for your detailed post regarding the lifecycle of Service Workers. Can I suggest that this information be added to Testing section of Workbox as one of the quirks of Safari's implementation of Service Workers? I see the section for Chrome there, it would make life a bit easier on DEVs testing on iOS/macOS safari. I tried your suggestion of quitting safari and the sync happened when I visited the web app.
@Jeff Posnick and Vijay thanks for this - I am dealing with a similar issue where I want to ensure that something that ends up in the Workbox queue on Safari will be uploaded at some point - did you manage to find any way to guarantee this without having to exit the app and come back to it?
@BruceM Sorry, I had to give up on Workbox and Service Workers for offline capability on iOS devices due to 1. lack of documentation resources online for safari in iOS. 2. lacklustre implementation of Service Workers in Safari. I don't think this is going to change. Apple wouldn't want their money pot taken away from them. 3. None of the service worker solutions are production ready in iOS and wouldn't be a quality solution even if corners are cut.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.