Me7e0r
Me7e0r

Reputation: 107

Service Worker fetch event not triggered for service worker itself

I noticed that the fetch event of a service worker is no longer triggered when the service worker script itself is loaded in the browser. For example, when we have a new version of a service worker, the old service workers fetch event is not triggered. As consequence, the old service worker can no longer check the content of the new service worker.

I'm sure this was possible before and I would like to know if this is a bug or if any changes were made regarding to that. I did not find anything in the official repository or W3C draft regarding to this change.

To verify that the fetch event is not triggered I programmed a small example service worker with a version number (see code). I have tested it the following way:

  1. Install first version of service worker
  2. Increase the version number to two.
  3. Reload the page -> So that the new sw.js file is installed in the browser.
  4. Check the chrome logs -> ChromeLogs ChromeLogs

Example 'sw.js':

const version = 1;
console.log(`SW with v${version} executed`);

async function onFetch(event) {
    // Not triggered for sw.js
    console.log(`fetching: ${event.request.url} with v${version}`);
    return await fetch(event.request);
}

async function onInstall() {
    console.log(`sw v${version} install`);
    await self.skipWaiting();
}

async function onActivate() {
    console.log(`sw v${version} activate`);
    await self.clients.claim();
}

self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
self.addEventListener('install', event => event.waitUntil(onInstall()));
self.addEventListener('activate', event => event.waitUntil(onActivate()));

As we can see from the logs, the sw.js file was not fetched, but another fiel (test.js) was fetched before the new service worker was installed. I included the test.js javascript file to see if the service worker was fetching anything. So from this test we can see that the fetch event is not triggered for service worker script itself.

What I would like to know is, is there any way to fetch the new service worker javascript file before it gets loaded within the old service worker? Are there any other events that make this possible? I do not need to intercept the script from executing or replacing the old service worker. I just want to check the content of the new service worker before it is loaded.

EDIT:

<html>
    <body>
        <h1>hello</h1>
        <script src="test.js"></script>
        <button onclick="runFetch()">fetch</button>
        <h2 id="swVersion"></h2>
        <script>
            navigator.serviceWorker.register('/sw.js'); // First Installation
            fetch('/sw.js'); // Triggers fetch event, but is independent from update routine.
            async function runFetch() {
                console.log(await fetch('/sw.js'));
            }
        </script>
    </body>
</html>

Upvotes: 0

Views: 2965

Answers (1)

Jeff Posnick
Jeff Posnick

Reputation: 56044

The service worker update check that is initiated by the browser always bypasses all service worker fetch handlers. It might end up being fulfilled by the HTTP Cache, although all modern browsers default to also bypassing the HTTP Cache and going straight to the network.

I'm fairly confident that no browser has ever triggered the previous service worker's fetch event handler when performing the service worker update check, as that's explicitly forbidden by the service worker specification (the service-workers mode of the update request is required to be set to 'none'). This helps developers avoid scenarios in which an old service worker could get "stuck" if it did something incorrect when processing the fetch event for a new service worker.

I'm not sure why you might have thought otherwise—perhaps you are thinking about the HTTP Cache interaction. Or perhaps you're thinking about a scenario in which a web app explicitly calls fetch('service-worker.js') to check to see if a service worker exists at a given URL, which will trigger the fetch handler of the service worker in control of a given page. But calling fetch('service-worker.js') is very different from the service worker update check.

Upvotes: 1

Related Questions