Service Worker and transparent cache updates

2019-05-11 16:12发布

问题:

I am trying to install a ServiceWorker for a simple, yet old, Django web app. I started working with the example read-through caching example from the Chrome team

This works well but isn't ideal because I want to update the cache, if needed. There are two recommended ways to do this based on reading all the other service-worker answers here.

  1. Use some server-side logic to know when the stuff you show has updated and then update your service worker to change what is precached. This is what sw-precache does, for example.

  2. Just update the cache version in the service worker JS file (see comments in the JS file on the caching example above) whenever resources you depend on update.

Neither are great solutions for me. First, this is a dumb, legacy app. I don't have the application stack that sw-precache relies on. Second, someone else updates the data that will be shown (it is basically a list of things with a details page).

I wanted to try out the "use cache, but update the cache from network" that Jake Archibald suggested in his offline cookbook but I can't quite get it to work.

My original thinking was I should just be able to return the cached version in my service worker, but queue a function that would update the cache if the network is available. For example, something like this in the fetch event listener

// If there is an entry in cache, return it after queueing an update
console.log(' Found response in cache:', response);
setTimeout(function(request, cache){
    fetch(request).then(function(response){
        if (response.status < 400 && response.type == 'basic') {
            console.log("putting a new response into cache");
            cache.put(request, response);
        }   
    })  
},10, request.clone(), cache);

return response;

But this doesn't work. The page gets stuck loading.

whats wrong with the code above? Whats the right way to get to my target design?

回答1:

It sounds like https://jakearchibald.com/2014/offline-cookbook/#stale-while-revalidate is very close to what you're looking for

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('mysite-dynamic').then(function(cache) {
      return cache.match(event.request).then(function(response) {
        var fetchPromise = fetch(event.request).then(function(networkResponse) {
          // if we got a response from the cache, update the cache
          if (response) {
            cache.put(event.request, networkResponse.clone());
          }
          return networkResponse;
        });

        // respond from the cache, or the network
        return response || fetchPromise;
      });
    })
  );
});


回答2:

On page reload you can refresh your service worker with new version meanwhile old one will take care of request.

Once everything is done and no page is using old service worker, It will using newer version of service worker.

this.addEventListener('fetch', function(event){
    event.responseWith(
        caches.match(event.request).then(function(response){
            return response || fetch(event.request).then(function(resp){
                return caches.open('v1').then(function(cache){
                    cache.put(event.request, resp.clone());
                    return resp;
                })
            }).catch(function() {
                return caches.match('/sw/images/myLittleVader.jpg');
            });
        })
    )
});

I recommend you to walk through below link for detailed functionality

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers