Workbox: GenerateSW service worker is removed in iOS when PWA is closed

Created on 24 May 2018  路  10Comments  路  Source: GoogleChrome/workbox

Library Affected:
workbox-webpack-plugin 3.2.0

Browser & Platform:
Safari 11.1 on iOS 11.3

Issue or Feature Request Description:
I'm creating a PWA and implementing a service worker via the workbox library. It works as expected on desktops (including Safari) and on mobile (but not Safari for iOS).

Whenever I have the PWA open on iOS and put the phone in flight mode I can refresh the PWA just fine and it's correctly served by the service worker. However, if I close the PWA completely and then reopen it, I will get the offline error page generated by Safari. I can see that await navigator.serviceWorker.getRegistrations() returns [] on the error page, so is it possible the service worker is somehow not persistent after the browser process has ended?

I know service workers are a new addition to Safari on iOS, but it works fine for the Twitter PWA, which doesn't seem to use workbox, so I would expect it to work for workbox as well.

When reporting bugs, please include relevant JavaScript Console logs and links to public URLs at which the issue could be reproduced.
There's not much to log. Everything looks fine before closing the PWA. No errors or warnings. The network inspector shows the full application being provided via the service worker. The cache is full of matches. The service worker is running and can be inspected. Upon closing the PWA completely and then reopening it, it's like none of it was ever there.

The following webpack plugin config is used and works fine with all other SW-enabled browsers (including Safari for MacOS):

new WorkboxWebpackPlugin.GenerateSW({
  swDest: "sw.js",
  clientsClaim: true,
  skipWaiting: true,
  navigateFallback: "/index.html",
  cacheId: "removed-from-example",
  runtimeCaching: [
    {
      urlPattern: new RegExp("https://removed.from.example"),
      handler: "staleWhileRevalidate"
    },
    {
      urlPattern: new RegExp("https://removed.from.example"),
      handler: "staleWhileRevalidate"
    }
  ]
});
Browser Compatibility

All 10 comments

https://bugs.webkit.org/show_bug.cgi?id=182444 might be relevant鈥攊t sounds like a fairly significant issue, given that Workbox does rely on importScripts() for pulling in both the runtime code and the precache manifest.

I'd recommend CC:ing yourself on that issue.

That's really significant @jeffposnick. Thanks for sharing!

I could imagine it could be fixed in Workbox by manually caching the Workbox related files, as well as the precache manifest.

I'm wondering if a temporary workaround for me could be to do runtime caching of those files.

EDIT:
I tried runtime caching as well as using globPatterns to no avail. I'm not sure if importScripts would even use the cache in iOS Safari. Workbox can be imported like any other dependency in a source service worker file, but the precache manifest should probably be inlined rather than imported.

It's a problem that even when importScripts eventually is fixed in Safari, there will still be older (the now current) versions of Safari that acts like they support importScripts properly, but they don't. And there's seemingly no way to detect this.

@jeffposnick Do you know if there's any temporary workaround available?

I've spent days on tryfixes, documentation, and looking through other github issues and mentions on the web. Any hint would be greatly appreciated :)

I assume the webpack plugin is too limited in this regard. Maybe the CLI would be useful in inlining all the assets?

(It looks like the bug has been fixed by Apple, so I'd test things out in the next Safari Technical Preview.)

The webpack plugins for Workbox all operate by adding in calls to importScripts(), for the Workbox runtime and for the precache manifest.

As an alternative to the webpack plugin, if you want to avoid relying on importScripts(), you could try the following:

  • Reference the pieces of Workbox that you plan on using as ES2015 module imports.
  • Use a ES2015-friendly bundler, like Rollup (or, I guess, webpack in a separate build) to create a single IIFE-formatted file that contains all of your custom code along with the Workbox code.
  • Make sure there's a precacheAndRoute([]) call in your custom code somewhere, and then use the workbox-cli in injectManifest mode to generate your precache manifest and inject it into the file directory.

The problem with this approach is that when using workbox-cli, you need to specify the files to match via glob patterns, as opposed to automatically picking up all of your webpack assets like the plugin can.

I'm going to close this, given that Apple has checked in code to resolve the issue with Safari, and we've laid out a few workarounds for avoiding importScripts() if you're willing to self-bundle.

Hi, sorry for the late reply.
I just wanted to say thanks for the elaborate answer and for your time.
I really appreciate it! Thanks!

This should be fixed in Safari TP 59, by the way: https://webkit.org/blog/8332/release-notes-for-safari-technology-preview-59/

This seems to be fixed in iOS12.1?

@joewoodhouse not, it doesn't. I have just updated to 12.1 and still have this issue.

I couldn't get it work with Safari too - Release 70 (Safari 12.1, WebKit 14607.1.13)

Was this page helpful?
0 / 5 - 0 ratings