I had trouble wrapping my head around clients.claim as well and none of the explanations made any sense to me so hopefully this answer helps anyone struggling as well.
To understand Clients.claim we have to look at the worker lifecycle.
- Installing; This is the first phase after registration. When the
oninstall
handler completes, the service worker is considered installed.
- Installed; The service worker is waiting for clients using other service workers to be closed.
- Activating; There are no clients controlled by other service workers. When the
onactive
handler completes, the service worker is considered activated.
- Activated; The service worker now controls the page.
skipWaiting and Clients.claim are designed to solve different problems.
Clients.claim ONLY has an effect on the very first time your webpage goes from an uncontrolled webpage to a controlled (by a service worker) webpage by registering a service worker.
skipWaiting is exactly what it says. It skips the waiting phase and moves directly to activating. Once activated it is now the active service worker for all clients. Clients being any window or tab that has a webpage open that is within the scope of your service worker.
So why do we need Clients.claim then?
This confused me and I bet it confused you too. The answer is best described in an example.
Imagine your webpage DOES NOT register a service worker and is therefor uncontrolled. You have two tabs (clients) of your webpage open. You make an update to your webpage so that it will now register a service worker.
You decide to reload the first tab (client), it will now fetch the script that registers the service worker and it will start to install. Once installed it notices that no other client is being controlled by a service worker so it does not have to wait and it can immediately safely activate the service worker and any fetch of a resource will now go through your service worker.
However, here is the catch, your other tab (client) will also have an active service worker now, BUT, it is not yet being controlled. Meaning any fetch will not go through the service worker yet. You need to reload any other tab (client) in order for it to be controlled by the active service worker. This is confusing, since if any new service worker hereafter becomes active by forcing it with skipWaiting, the other tabs (clients) will immediately be controlled by the new active service worker. So I emphasize the reload part is needed ONLY when an uncontrolled webpage becomes controlled.
Enter Clients.claim. When you call self.clients.claim() in the first service worker when it becomes activated, like so:
self.addEventListener('activate', event => {
event.waitUntil(clients.claim());
});
It will make sure the other tabs (clients) that were uncontrolled, but have an active service worker, will get controlled by the active service worker. Meaning any fetch to a resource will now go through the active service worker. Without Clients.claim the service worker is not used until the page is reloaded.
Again, if all the webpages are being controlled by a service worker already. If a NEW service worker is detected and installed, it normally waits until all tabs with the webpage (clients) are closed. The next time you visit the webpage it will have activated the new service worker and the webpage is being controlled by it.
However, if you don't close all the clients and you force the new service worker by using skipWaiting it will immediately become active for all clients and also controlled. Meaning any new fetch for a resource from ANY of the clients will now immediately go through your new service worker. Now you don't need to use Clients.claim in order for the other clients to start using your new service worker.
This was my attempt, hopefully it helped someone.
registration.update()
isn't required to check for an updated service worker script. That's already done automatically by the browser after a navigation request.registration.update()
allows you to for a check without having to wait for navigation requests, and it's usually not necessary. – Discussant