DEV Community

Carmen Bourlon
Carmen Bourlon

Posted on

Let's Take This Offine: How to version your service worker cache

This post originally appeared on carmalou.com

A lot of service worker examples show an install example that looks something like this:

self.oninstall = function(event) {
    caches.open('hard-coded-value')
    .then(function(cache) {
        cache.addAll([ /.../ ])
        .catch( /.../ )
    })
    .catch( /.../ )
}

Let's do a quick overview of the above code. When a browser detects a service worker, a few events are fired, the first of which is an install event. That's where our code comes in.

Our function creates a cache called hard-coded-value and then stores some files in it. There's one small problem with this ... our cache is hard-coded!

There's an issue with that. A browser will check in with a service worker every 24 hours and re-initiate the process, but only if there are changes. You might change your app's CSS or JavaScript, but without a change to the service worker, the browser will never go and update your service worker. And if the service worker never gets updated, the changed files will never make it to your user's browser!

Fortunately, there's a pretty simple fix -- we'll version our cache. We could hard code a version number in the service worker, but our app actually already has one. So handy!

We'll use our app's version number from the package.json file to help. This method also requires (pun intended) us to be using webpack.

In our service worker, we'll require our package.json file. We'll grab the version number from the the package.json and concatenate that to our cache name.

self.oninstall = function(event) {
    var version = require(packagedotjson).version;
    caches.open('hard-coded-valuev' + version)
    .then(function(cache) {
        cache.addAll([ /.../ ])
        .catch( /.../ )
    })
    .catch( /.../ )
}

Turns out, there's actually an even better way than above using some of webpack's built-in tools. A problem with the above code is that your package.json file will get bundled into your service worker. That's pretty unnecessary and it's going to increase the size of your bundle.

We'll use DefinePlugin to make this even cleaner.

Let's add a property to our DefinePlugin function in our webpack file. We'll call it process.env.PACKAGEVERSION.

It might look like this:

var version = require(packagedotjson).version;
new webpack.DefinePlugin({
  'process.env.PACKAGEVERSION': JSON.stringify(version)
});
</code>
</pre>

<sub>Source: [webpack `DefinePlugin`](https://webpack.js.org/plugins/define-plugin/)</sub>

And then in our service worker instead of referencing `version` directly, we'll use `process.env.PACKAGEVERSION`. It'll look like this:

<pre>
<code class="language-javascript">
self.oninstall = function(event) {
    caches.open('hard-coded-valuev' + process.env.PACKAGEVERSION)
    .then(function(cache) {
        cache.addAll([ /.../ ])
        .catch( /.../ )
    })
    .catch( /.../ )
}

webpack will work behind the scenes for you, and swap out the 'process.env.PACKAGEVERSION' for the proper number. This solves the problem of needing to update our service worker, and it handles it in a clean, simple way. Plus it will help us out when we need to clean up former caches. I'll write about that next, so stay tuned!

If you want to learn more about service workers, I hope you'll head over to serviceworkerbook.com and sign up for my mailing list, and follow me on Twitter! You'll be the first to know when my book, 'Let's Take This Offline' is out!

Top comments (0)