Your PWA is going to break in August 2021

UPDATE: On April 14, Google announced they would be pausing their plan to roll out this feature. Check out my follow-up article here.
If you have a PWA and you’ve recently looked at your console or app manifest, you may have noticed this message:
Page does not work offline. Starting in Chrome 93, the installability criteria is changing, and this site will not be installable. https://developer.chrome.com/blog/improved-pwa-offline-detection for more information
Or if you’re using Edge:
Site cannot be installed: Page does not work offline. The page will not be regarded as installable after Edge 93, stable release August 2021.
You see, before Chrome 93, all you had to do for Chrome to make your app installable was to pretend to listen to the fetch event in your service worker. You didn’t even really have to do anything at all. All you had to do was register a listener. And that was it. Easy-peasy.
I guess Google took issue with the hack. Truth be told, there are probably too many sites — many of which probably shouldn’t even be installable in the first place— that used ugly hacks like this:
With the upcoming release of Chrome, you’ll have to actually make use of the cache or your PWA will no longer be installable.
Why is this happening?
Google’s dogma is that a PWA should never display the Chrome’s default offline screen. Instead, all PWAs should either be available offline or show some sort of offline page as a fallback. Thanks to the hack above, you weren’t actually forced to make your PWA work offline. Now you will be (or you’ll have to find an even uglier hack to not have to).

Now, why a custom page that pretty much does nothing useful except say “you’re offline” is a better fallback than the default dinosaur page is a bit unclear. People do know what that page means. It offers clears directions on what to do to get back online. And it’s built by Google itself (so it’s not like it’s redirecting traffic to some unrelated third-party site).
But apparently, Google doesn’t like its own solution. So instead you’ll have to build one yourself (which — in all likelihood — won’t be as good as Google’s. That is, unless you can do better than the Dinosaur Game obviously).

Side note: I’m building Progressier, specifically so that you don’t have to deal with Google/Apple/Microsoft/Samsung/Firefox latest whims (we take care of that for you — and it’s free), but if you absolutely insist on inflicting that on yourself, below is what you’ll have to do for your app to become compliant.
What can I do to fix this?
First, you’ll have to populate your “fetch” handler so that it actually does something useful, i.e. cache resources. There are two main ways to go about this.
- With the Network-Falling-Back-To-Cache strategy, your service worker will first try to retrieve the resource from your server. Then when it can’t do that — because for example, you’re offline — retrieve it from the cache (if it exists there).
- With the Stale-While-Revalidate strategy, your service worker first looks into the cache while also issuing the request to the server. If the resource exists in the cache, it will send it back to the client right away — resulting in a seemingly instantaneous load. When (and if) the server responds to the request successfully, it will save the updated response in the cache. The main drawback of this approach is that resources that you’ll serve will always be one version behind.
There are a couple of other marginally-useful strategies. With Cache-First, you don’t revalidate resources at all. Resources can never be updated once they’re in the cache — but the strategy can also lighten your AWS bill. With Network-Only, you don’t make use of the cache at all, so that resources are always fresh. And there is also a Cache-Only strategy, which is pretty much useless.
Secondly, you’ll also likely have to precache resources in the “install” event handler. Fun fact: this event fires when the service worker is installed. Not when the user has installed your app. For some reason, I see many developers getting these two concepts mixed up.
The issue with resource caching
So there is one main issue that remains with the way service workers handle offline. As you update your app and create new resources, you’ll have to remember to precache them too if you want everything to always work offline. That’s potentially a lot of headaches — although a library like Workbox does make things a bit easier. Regardless, this highlights one of the worst aspects of PWAs. Making a PWA is not a one-time effort. There are a bunch of things you’ll have to update regularly or they’ll break.
At Progressier, our solution (as of March 2021) is currently partially Chrome 93 compliant. Most PWAs that have Progressier already work offline — although it depends a bit on the exact structure of your app. We’ll be fully compliant by the time Chrome 93 is released so that every single app that’s running Progressier is available offline regardless of how they’re structured.
How we’ll fix the problem above: our bot will regularly visit your app and inspect network requests. When we see new resources, we’ll automatically add them to the list of resources to cache. With Workbox, you have to manually build caching strategies. With Progressier, strategies are built for you automatically.
Do you have any questions? Or need help making your PWA Chrome 93 compliant? Comment or email me at kevin@progressier.com