Caching Service Workers

Service Workers are JavaScript client-side proxys which allow caching of request/response pairs to facilitate offline support. They are the foundation of Progressive Web Apps which bring web applications closer to the functionality and performance of native apps. This post illustrates how to effectively cache service workers so they can update correctly.

HTTP Caching of JavaScript

It is good practice to utilise HTTP caching of JavaScript to improve your apps performance.

This can be achieved using Apache with a configuration similar to this:

# Cache files with .js extension
<FilesMatch ".js$">
Header set Cache-Control "max-age=31536000"
</FilesMatch>

This will allow clients to cache any files with a .js extension for one year with no need to revalidate the cached copy with the server. Whenever it is required to update the version of the scripts clients have, the cache can be broken by altering the filename of the script. A common way to do this is to insert a truncated hash of the file’s content into the filename and update all requests to match this. The hash could alternatively be inserted into the query string of the request.

<!-- inserting a truncated hash into the filename and query string -->
<script src="app.70e447ffdd.js"></script>
<script src="app.js?v=70e447ffdd"></script>

Caching Service Workers

Whenever a page with a service worker is visited, the browser will attempt to fetch the service worker from the server to check if it has been updated (byte-different) and if so it will update it. It is thus imperative that it does not use the cached version if there is a new version on the server; this would prevent the update as the installed version will be compared to itself!

It must be ensured that the service worker both maintains an identical filename and that browsers are prohibited from using a cached version without server revalidation.

# Do not cache files which end with 'service-worker.js'
<FilesMatch "service-worker.js$">
Header set Cache-Control "no-cache"
</FilesMatch>

In the above example I have used ‘no-cache’ which allows HTTP caching of the service worker but it must be revalidated before use. This meets our criteria for allowing the correct updating of service workers.

It is worth noting that if you do allow caching without server revalidation then the browser will only cache for a maximum of 24 hours. After 24 hours the browser will use the network to check for a new version of the service worker.

no-cache vs. no-store

The values of Cache-Control can be quite tricky to get to grips with. To prevent undesired use of old file versions you can use ‘no-cache’ or ‘no-store’.

  • ‘no-cache’ - CACHE, but revalidate with the server before using
  • ‘no-store’ - DO NOT CACHE whatsoever

For some fun why not try the Cache-Control questions from Jake Archibald and Paul Lewis’s Big Web Quiz!

Conclusion

Service Workers are a very powerful tool which can greatly improve performance and allow offline support but to ensure they are correctly updated care must be taken to distinguish their caching strategy from that of other JavaScript files.