How does a browser retrieve a resource from a server?
Caching is not the most intuitive concept to grasp. This is how a browser typically interacts with a server:
Browser ➔ Server ➔ Browser
So for example, when an image is loaded on a web page, your browser attempts to make a request to the URL at which the image is located. If the server receiving the request recognizes that URL, it will send back the data of the image so that the browser can display it for you.
What's a service worker?
By adding a service worker (or Progressier) to your app, you can add an additional middleman between the browser and your server. The job of a service worker is to intercept requests before and after they hit the responding server, allowing a bunch of cool new possibilities.
Browser ➔ Service worker ➔ Server ➔ Service worker ➔ Browser
Service workers work independently from your app. That means that as long as your browser is open, the service workers for all websites you visited are all still running. This is what allows you to receive push notifications from a website you're not currently visiting.
What can you do with a service worker?
Service workers offer a bunch of new possibilities for making your apps look and feel more like native apps. A few examples of things you can do with a service worker:
Make your app work completely offline
Force your app to update its content
Use placeholder images
Make loading of a page near-instant
Retry POST requests later when offline
Cache resources that you’ll need later ahead of time
Build redundancy — if a request to a URL fails, you can try a mirror URL instead.
Prevent the browser from caching a resource completely
Define caching strategies and apply them to specific types of resources
What's a caching strategy?
Service workers enable you to alter the requests and responses made to and received from servers. With caching strategies, you tell the browser exactly how you want to store and retrieve each type of resource. There are 4 different caching strategies:
Network Only
By default, browsers tend to cache resources... somewhat unpredictably. With the Network Only strategy, you can override this behavior. You essentially tell the browser: "always get this type of resources from the network and only from the network. Don't look in the cache under any circumstances". This is useful for certain types of resources where data must never be stale.
Fun fact: When we launched coronavirus.app in January 2020, we made use of this strategy for the COVID data itself. Back then, people wanted to see near real-time data. Whenever we were a bit late on updates, we would receive dozens of emails from angry users asking why our data wasn't up-to-date. In that context, we found it preferable to show no data at all than stale data to users with connectivity issues.
Network First
This is probably the safest strategy. So if you're not sure, use this one. Basically, with this strategy, you tell the browser to always ask the network for resources first. If the network responds successfully, the response is saved in the cache. If that first network request fails, then it looks for a response in the cache.
This strategy de facto makes your app available offline. You use the cache as a fallback for the cases when the network is somehow not accessible.
Stale-While-Revalidate
This strategy tends to make resources load faster. But it can also result in displaying stale data to users, so use it sparingly and only with non-essential resources (so probably not with say... financial data). With this strategy, you tell the browser: "Okay browser, check the cache and if we have a response there, let's use this right now. And while you're doing that, also check with the network to see if there is an updated version of the resource and update the cache accordingly."
Asking your device's cache for resources is orders of magnitude faster than asking a server that may literally be located across the world. So by using this strategy, resources will seem to load nearly instantly. But they may be one version behind.
Cache First
This one is the money-saving strategy. It's similar to the previous one, except you never ask the browser to revalidate the resource if it already has it available in the cache. After the initial load, as long as the resource is in the cache, the network is no longer used. Fewer calls to your server = money saved.
This is a DANGEROUS strategy so be very careful. If a resource is in the cache, it will no longer be updated. Only use this with resources that you are sure will never need to be updated. Or use this with resources for which you have a different update mechanism. A good update mechanism is to append a version number to the URL of a resource. So for example, https://example.com/resource1 and https://example.com/resource1?v=1 are two different resources from the point of view of the browser.
Bonus: what about Cache Only?
Workbox technically offers a fifth strategy that does not make use of the network at all. Progressier does not. Resources are exclusively retrieved from the cache. If they don't exist in the cache, the service worker will return an error without even asking the network.
However, I honestly can't think of a single-use case for this. It doesn't have any advantages over any of the strategies. And it has the potential of completely screwing up your app (all requests will suddenly fail unless they're already cached!). That's why we don't allow you to choose Cache Only in Progressier.