cache.adderall(⚡)

the impatient version of cache.addAll()

Speed up your Service Workers and save bandwidth with a drop-in replacement for cache.addAll()

cache.addAll() receives a list of URLs, and fetches each of them from the network.

It returns a promise that only resolves if all the URLs were added to the cache successfully.

cache.adderall() receives a list of URLs, then the lazy bastard looks for them in existing caches, only fetching them from the network if it has to.

It returns a promise that only resolves if all the URLs were added to the cache successfully.

What does cache.adderall() do?

When your site installs a new service worker, you are probably using cache.addAll() to cache all the URLs it needs. Then, every time you make any change to the service worker, or change the list of files to cache, the install event runs again and fetches every single file again… This can be terribly inefficient and wasteful.

cache.adderall() is very much like the browser's native cache.addAll(). The only difference is that when you call it, cache.adderall() first looks for the files you are trying to cache in the user's existing caches. If any of these files are found, they will be copied over to the new cache, so that your service worker only needs to download new files. Any file that isn't already cached will be fetched as usual using the native cache.addAll().

This saves bandwidth, speeds up your service worker installation, and saves your users from downloading the same files over and over again, every time your service worker changes.

Using cache.adderall()

Once you've imported cache.adderall() into your service worker, calling it is very much like calling cache.addAll(). The only difference is that instead of calling addAll() on a cache object and passing it an array of URLs, you call adderall.addAll() passing it the cache object followed by the array of URLs.

// In your service worker
importScripts('https://cdnjs.cloudflare.com/ajax/libs/cache.adderall/1.0.0/cache.adderall.js');

var STATIC_FILES = [
  'video/cache.adderall.demo.mp4',
  '/bootstrap/3.3.7/css/bootstrap.min.css',
  '/js/2.6.0/annyang.min.js'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('cache-v1').then(cache =>
      adderall.addAll(cache, STATIC_FILES)
    )
  );
});
// In your service worker
  

var STATIC_FILES = [
  'video/cache.adderall.demo.mp4',
  '/bootstrap/3.3.7/css/bootstrap.min.css',
  '/js/2.6.0/annyang.min.js'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('cache-v1').then(cache =>
         cache.addAll(STATIC_FILES)
    )
  );
});

When the service worker above first runs in your user's service worker, it will behave exactly like cache.addAll(). But let's say you then decide to add a 4th file to the STATIC_FILES array, this is where cache.adderall() shines. Where cache.addAll() would download every file again, adderall.addAll() only downloads the new file, and copies existing files from the old cache to the new (or just leaves them where they are, if both versions use the same cache).

Wait a second… what if my files changed?

cache.adderall()'s lazy approach is great for files that never change (e.g. style.v38.css, or/js/2.6.0/annyang.min.js). But if some of your files may change between versions, while their URL stays the same (e.g. index.html, app-settings.json), you can ask cache.adderall() to skip its lazy behavior for those files.

Any file that needs to be fetched from the network every time you update your service worker can be passed in a second array of URLs as cache.adderall()'s third argument.

// In your service worker
importScripts('https://cdnjs.cloudflare.com/ajax/libs/cache.adderall/1.0.0/cache.adderall.js');

var STATIC_FILES = [
  'video/cache.adderall.demo.mp4',
  '/bootstrap/3.3.7/css/bootstrap.min.css',
  '/js/2.6.0/annyang.min.js'
];

var MUTABLE_FILES = [
  'app-settings.json',
  'index.html'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('cache-v2').then(cache =>
      adderall.addAll(cache, STATIC_FILES, MUTABLE_FILES)
    )
  );
});

Any URLs passed in the 3rd argument, are handled directly by the native cache.addAll().

In fact, the following two commands do exactly the same thing:

cache.addAll(['/index.html', '/main.css']);
adderall.addAll(cache, undefined, ['/index.html', '/main.css']);

Remember: adderall.addAll(cache, immutableURLs, mutableURLs);

What about HTTP caching?

If your server is configured to serve each different file with the correct caching headers, serving mutable content with a Cache-Control: no-cache header, and immutable content with Cache-Control: max-age=31536000, then you might not need cache.adderall() at all. In fact, this is the prefered approach. You can read more details on caching header best practices in Jake Archibald's excellent post.

If however you are in an environment where you can't control the caching headers of individual files, can't access the server, are not speaking with Dev Ops over a relatively minor incident involving yogurt left in the office fridge, or you are just using GitHub Pages - give cache.adderall() a try.

Thanks Jake Archibald and Jeffrey Posnick for helping sort this out.

cache.adderall() is a free, open source, community effort.

Please help spread the word:

Check out my new book - Building Progressive Web Apps.

Building Progressive Web Apps