title: Bypass default caching policy if file is managed by service worker
body: <p>I am using Google's <code>workbox-cli</code> tool in order to precache some of the files on my website. Is it possible to setup the webserver to return the following in the HTTP response header for all files by default:</p>
  
  <pre><code>cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public
  </code></pre>
  
  <p><strong>But</strong>, have the webbrowser use the follwing instead only if the file is going to be precached by the service worker:</p>
  
  <pre><code>cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public
  </code></pre>
  
  <p>So, I would like the service worker to change <code>max-age=86400</code> into <code>max-age=0</code> in the webserver's response header before precaching the file. This makes the service worker fetch files, that have changed according to the revision in <code>sw.js</code>, from the webserver instead of retrieving them from local cache. Any files not managed by the service worker are cached for 86400 seconds by default.</p>
  
  <h2>Some background info</h2>
  
  <p>Currently, I am using the following bash script to setup my <code>sw.js</code>:</p>
  
  <pre><code>#!/bin/bash
  if [ ! -d /tmp/workbox-configuration ]; then
  mkdir /tmp/workbox-configuration
  fi
  cat &lt;&lt;EOF &gt; /tmp/workbox-configuration/workbox-config.js
  module.exports = {
    "globDirectory": "harp_output/",
    "globPatterns": [
  EOF
  ( cd harp_output &amp;&amp; find assets de en -type f ! -name "map.js" ! -name "map.json" ! -name "markerclusterer.js" ! -name "modal.js" ! -name "modal-map.html" ! -name "service-worker-registration.js" ! -name "sw-registration.js" ! -path "assets/fonts/*" ! -path "assets/img/*-1x.*" ! -path "assets/img/*-2x.*" ! -path "assets/img/*-3x.*" ! -path "assets/img/maps/*" ! -path "assets/img/video/*_1x1.*" ! -path "assets/img/video/*_4x3.*" ! -path "assets/js/workbox-*" ! -path "assets/videos/*" ! -path "de/4*" ! -path "de/5*" ! -path "en/4*" ! -path "en/5*" | sort | sed 's/^/"/' | sed 's/$/"/' | sed -e '$ ! s/$/,/' &gt;&gt; /tmp/workbox-configuration/workbox-config.js )
  cat &lt;&lt;EOF &gt;&gt; /tmp/workbox-configuration/workbox-config.js
    ],
    "swDest": "/tmp/workbox-configuration/sw.js"
  };
  EOF
  workbox generateSW /tmp/workbox-configuration/workbox-config.js
  sed -i 's#^importScripts(.*);$#importScripts("/assets/js/workbox-sw.js");\nworkbox.setConfig({modulePathPrefix: "/assets/js/"});#' /tmp/workbox-configuration/sw.js
  sed -i 's/index.html"/"/' /tmp/workbox-configuration/sw.js
  uglifyjs /tmp/workbox-configuration/sw.js -c -m -o harp_output/sw.js
  </code></pre>
  
  <p>On my Nginx webserver the following HTTP header is delivered by default:</p>
  
  <pre><code>more_set_headers "cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public";
  </code></pre>
  
  <p>But, if the requested ressource is not handled by the service worker, the default <code>cache-control</code> setting is overwritten:</p>
  
  <pre><code>location ~ ^/(assets/(data/|fonts/|img/(.*-(1|2|3)x\.|maps/|video/.*_(1x1|4x3)\.)|js/(map|markerclusterer|modal|service-worker-registration|sw-registration)\.js|videos/)|(de|en)/((4|5).*|modal-map\.html)) {
      more_set_headers "cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public";
  }
  </code></pre>
  
  <h2>Problem with the current approach (see background info)</h2>
  
  <ol>
  <li>I have to keep track of the files and update <code>nginx.conf</code>correspondingly.</li>
  <li><code>max-age=0</code> is used also for webbrowsers that don't support service-workers. So, they request the ressources from the webservers on each page visit.</li>
  </ol>
  
  <h2>1st Update</h2>
  
  <p>My desired precaching behaviour can be illustrated with two of the <a href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies" rel="nofollow noreferrer">workbox strategies</a>. I want the service worker to show below behaviour as described in scenario 1 and 2, although <code>cache-control: max-age=86400</code> is delivered in the HTTP header by the webserver for an asset (e.g. <code>default.js</code>).</p>
  
  <p><strong>Scenario 1: revision in sw.js didn't change</strong></p>
  
  <p>The webpage is accessed, the <code>sw.js</code> file is retrieved from the webserver due to <code>max-age=0</code> and the webbrowser noticed that the revision for <code>default.js</code> didn't change. In this case, <code>default.js</code> is retrieved from the precache cache:</p>
  
  <p><a href="https://i.stack.imgur.com/3fP76.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3fP76.png" alt="enter image description here"></a></p>
  
  <p><strong>Scenario 2: revision in sw.js did change</strong></p>
  
  <p>The webpage is accessed, the <code>sw.js</code> file is retrieved from the webserver due to <code>max-age=0</code> and the webbrowser noticed that the revision of <code>default.js</code> changed. In this case, <code>default.js</code> is retrieved from the webserver:</p>
  
  <p><a href="https://i.stack.imgur.com/TCm2A.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TCm2A.png" alt="enter image description here"></a></p>
  
  <h2>2nd Update</h2>
  
  <p>Basically, the desired strategy is similar to the <a href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies#network_first_network_falling_back_to_cache" rel="nofollow noreferrer">network-first strategy</a>. But, step 2 is only taken if the revision of the file in <code>sw.js</code> has changed.</p>
  
  <p><a href="https://i.stack.imgur.com/PWnyS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/PWnyS.png" alt="enter image description here"></a></p>
  
  <h2>3rd Update</h2>
  
  <p>If I am not mistaken, there is already <a href="https://jakearchibald.com/2016/caching-best-practices/" rel="nofollow noreferrer">some work</a> on this:</p>
  
  <pre><code>self.addEventListener('install', event =&gt; {
    event.waitUntil(
      caches.open(`static-${version}`)
        .then(cache =&gt; cache.addAll([
          new Request('/styles.css', { cache: 'no-cache' }),
          new Request('/script.js', { cache: 'no-cache' })
        ]))
    );
  });
  </code></pre>