14

The question title says it all.

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/react-redux/sw.js').then(() => {
        console.log('registered');
    }, err => console.log(err));
}

EDIT

It looks like the root of the problem is the path

navigator.serviceWorker.register('/react-redux/sw.js')

if I move the sw code, so that I have

navigator.serviceWorker.register('swRoot.js').then(() => {

then everything works properly. I tried just about everything I can think of above, from dropping the leading slash in /react-redux, to adding a {scope: of './', '/', '/react-redux', and none worked (with some causing errors).

Does anyone know what config magic is needed to be able to load a service worker from somewhere other than the root of your domain?


and then my entire sw.js

self.addEventListener('install', function(event) {
    console.log('hello');
    try {
        console.log('typeof System in install', typeof System);
    } catch(e){}

    console.log('caching');
    event.waitUntil(
        caches.open('v1').then(function(cache) {
            console.log('caching - getting');
            return cache.addAll([
                '/react-redux/a.js'
            ]);
        }).catch(function(error){ console.log('error', error) })
    );
});

console.log('ADDING FETCH')
self.addEventListener('fetch', function(event) {
    console.log('fetching ->', event.request);
    event.respondWith(
        caches.match(event.request)
                .then(function(response) {
                    // Cache hit - return response
                    if (response) {
                        return response;
                    }
                    return fetch(event.request);
                })
    );
});

I never ever get the console.log('fetching ->', event.request); message. I even added this silliness to try to force the issue.

setTimeout(() => fetch('/react-redux/foo.css').then(r => console.log(r)), 1000);
setInterval(() => fetch('/react-redux/foo.css').then(r => console.log(r)), 5000);

I see the fetch events running, but the service worker never says it's hitting those event handlers.

Moreover, I do get notified that the SW is registered, and when I update sw.js, close and re-open, I see all the logging statements indicating that things are installing correctly.

Community
  • 1
  • 1
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • Can you create a plnkr http://plnkr.co to demonstrate? – guest271314 Dec 08 '16 at 20:09
  • @guest271314 - It'd likely be non-trivial to do so. I'm hoping a SW expert can look at the code and see what the problem may be. – Adam Rackis Dec 08 '16 at 20:30
  • plnkr allows creation of files and `ServiceWorker`. `javascript` at Question should be able to be reproduced – guest271314 Dec 08 '16 at 20:33
  • 1
    The difficult part would be getting resources in place to request from within plnkr, to test whether they were working with the SW. – Adam Rackis Dec 08 '16 at 20:35
  • Not sure what you mean? You can create new files at plnkr by clicking _New file_, for example, `foo.css`, then call `fetch()` with file name as parameter within `script.js` – guest271314 Dec 08 '16 at 20:38

3 Answers3

9

You're on the right track, it seems to be a scoping issue.

To change the scope of a service worker, it must be done when registering, like this:

navigator.serviceWorker.register('scripts/sw.js', { scope: '/' })

Then the server must return the following header in the response to acknowledge this scope change.

Service-Worker-Allowed: /

See this answer

Derek
  • 967
  • 1
  • 9
  • 16
3

Getting fetch interception working seems to require that the registered service worker be at or above the level of the tree with the HTML file registering the worker. Below fails.

In Chrome, be sure to look at "Service Worker" under "Application". Even registering below results in a Service Worker which is activated and running, but when the location is at or above the HTML page, you also get an entry listed under "Clients". The presence of this seems to correspond exactly to when the fetch will be intercepted.

Andy Valencia
  • 166
  • 1
  • 5
2

Attach fetch event listener within install event handler

self.addEventListener('install', function(event) {
  console.log("install");
  try {
    console.log('typeof System in install', typeof System);
  } catch (e) {}

  console.log('caching');
  event.waitUntil(
    caches.open('v1').then(function(cache) {
      console.log('caching - getting');
      return cache.addAll([
        'a.js'
      ]);
    }).catch(function(error) {
      console.log('error', error)
    })
  );

  self.addEventListener('fetch', function(event) {
    console.log('fetching ->', event.request);
    event.respondWith(
      caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
        return fetch(event.request);
      })
    );
  });
});

plnkr https://plnkr.co/edit/WuJCZSD0V4idG1Ra7VMb?p=preview

guest271314
  • 1
  • 15
  • 104
  • 177
  • Hm - no, it looks like the problem is the path to the service worker - the fetch subscription works fine as is, once that's rectified - see edit above. If you have any info on why the SW is so sensitive to where it lives, I'm all ears :) – Adam Rackis Dec 08 '16 at 23:01
  • @AdamRackis Full disclosure: have little experience with `ServiceWorker`; just tried different configurations of `javascript` at Question to derive the Answer. Have you tried using the full path to the resource? – guest271314 Dec 08 '16 at 23:06
  • Cool - well thanks for the effort - and yeah, tried just about every path permutation I could think of. Thanks again for the time! – Adam Rackis Dec 08 '16 at 23:07