title: Service Worker: how to update the cache when files changed on the server?
body: <p>What cache strategies are you using? I read the Offline Cookbook and the simplest strategy to use is to cache static content and the left out the API calls.</p>
  
  <p>This strategy seems something like this:</p>
  
  <ol>
  <li>Check if the request is already in cache</li>
  <li>If not add the request, response pair to cache</li>
  <li>Return response</li>
  </ol>
  
  <p><em>How to update the cache if on the server side files has changed?</em> Currently the clients gets always the cached results.</p>
  
  <p>Here is my cache strategy's code:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// You will need this polyfill, at least on Chrome 41 and older.
  importScripts("serviceworker-cache-polyfill.js");
  
  var VERSION = 1;
  
  var CACHES = {
      common: "common-cache" + VERSION
  };
  
  // an array of file locations we want to cache
  var filesToCache = [
      "font-cache.html",
      "script.js",
  ];
  
  var neededFiles = [
      "index.html"
  ];
  
  var errorResponse = function() {
  
      return new Response([
              "&lt;h2&gt;Failed to get file&lt;/h2&gt;",
              "&lt;p&gt;Could not retrive response from cache&lt;/p&gt;"
          ].join("\n"),
          500
      );
  };
  
  var networkFetch = function(request) {
  
      return fetch(request).then(function(response) {
  
          caches.open(CACHES["common"]).then(function(cache) {
  
              return cache.put(request, response);
          });
  
      }).catch(function() {
          console.error("Network fetch failed");
          return errorResponse();
      });
  }
  
  this.addEventListener("install", function(evt) {
      evt.waitUntil(
          caches.open(CACHES["common"]).then(function(cache) {
  
              // Cache before
              cache.addAll(filesToCache);
              return cache.addAll(neededFiles);
          })
      );
  });
  
  this.addEventListener("activate", function(event) {
  
      var expectedCacheNames = Object.keys(CACHES).map(function(key) {
          return CACHES[key];
      });
  
      console.log("Activate the worker");
  
      // Active worker won"t be treated as activated until promise resolves successfully.
      event.waitUntil(
          caches.keys().then(function(cacheNames) {
              return Promise.all(
                  cacheNames.map(function(cacheName) {
                      if (expectedCacheNames.indexOf() ===
                          -1) {
                          console.log(
                              "Deleting out of date cache:",
                              cacheName);
  
                          return caches.delete(cacheName);
                      }
                  })
              );
          })
      );
  });
  
  self.addEventListener("fetch", function(event) {
      console.log("Handling fetch event for", event.request.url);
  
      event.respondWith(
  
          // Opens Cache objects
          caches.open(CACHES["common"]).then(function(cache) {
              return cache.match(event.request).then(function(
                  response) {
  
                  if (response) {
                      console.log("Found response in cache", response);
  
                      return response;
                  } else {
  
                      return networkFetch(event.request);
                  }
              }).catch(function(error) {
  
                  // Handles exceptions that arise from match() or fetch().
                  console.error(
                      "  Error in fetch handler:",
                      error);
  
                  return errorResponse();
              });
          })
      );
  });</code></pre>
  </div>
  </div>
  </p>