iosprogressive-web-appsservice-workeripadosipados16

iOS PWA - After updating the service worker once, killing the app & restarting it, another copy of the active service worker is waiting


I have an app that registers a service worker and gives the user the chance to trigger a service worker update when a new service worker is waiting. Everything seems to be functioning well on Android, and it's also functioning fairly well on iOS. However, in standalone mode on iOS, after making one service worker update, it seems like the app keeps trying to install the same service worker over and over again.

Using an iPad running iPadOS 16.4.1, I take the following steps to produce the issue:

  1. I install the PWA, and it is running service worker A.
  2. I deploy a new service worker (service worker B). The app detects that there is an update to the service worker and pulls the new one. Once service worker B reaches a state of "waiting," the app presents a prompt that allows me to post a skipWaiting message to service worker B, and I do so.
  3. Service worker B takes over.
  4. I completely kill and reopen the PWA.
  5. The app is running service worker B, and no new service worker has been deployed, but another copy of service worker B has somehow reached the waiting state, so the app, checking for any service workers in the waiting state and finding one, again prompts me to trigger an update even though one shouldn't be needed.

I've confirmed via Safari's Web Inspector that service worker A is running initially, that service worker B is then loaded and made active, that it is service worker B that's running after the app is killed and then restarted, and that the subsequently loaded service worker is a copy of service worker B.

Is this a known limitation/quirk of PWAs running on Apple devices, or does it sound like something's gone amiss on my end to cause it?

I'm not running into the same issue when I kill the PWA while it's still running service worker A and service worker B hasn't been deployed (it's only after I've updated the service worker at least once that the issue crops up). So my current guess is that perhaps on iOS the PWA retains information about the original service worker it was installed with and compares against that original service worker rather than the currently active service worker when looking for updates. I haven't been able to find any documentation that supports that theory yet though.


Solution

  • I'm not entirely sure why this fixed the issue, but in case it helps others:

    I was making a call to the service worker's registration.update() method on a set interval to check for updates, and originally I was doing so within my service worker's code. Simply moving that logic to the app code and making the registration.update() call from there instead of from the service worker ended up fixing the problem for me. Since it works just fine on Android either way and since the documentation for the update method indicates that a byte-by-byte identical service worker shouldn't be installed as a new service worker, I suspect this is just an iOS quirk.