Offline capable Gatsby site on Cloudflare Workers

Getting your Gatsby site to work properly on Cloudflare Workers can be a bit difficult but I am here to help!


February 8, 2020 - 1 min read
gatsbycloudflare workers

I recently moved my blog over from Hugo to Gatsby. One of the issues I ran into was that the offline plugin did not work properly on Cloudflare Workers.

Cloudflare Workers

This is essentially the Cloudflare version of Lambda@Edge but with much faster cold start. I decided to give that a try for my new blog mostly because it seemed like a lot of fun to try and the deployment process is super easy thanks to the Wrangler tool.

Offline Gatsby

Gatsby can use service workers to make your site work offline by using a plugin. The site is then cached by a service worker and will work just fine offline and with improved performance for slow connections. The service worker will then check two files in the backgrounds: app-data.json and page-data.json. These files are not to be cached to make the site update properly without resorting to hard reloads to get new content.

The problem is that Cloudflare Workers will cache these files by default, both on their CDN as well as in the browser. This means that the service worker thinks that nothing has updated and the page will never update with new content without doing hard reloads. I do not know why the Cloudflare Workers cache json files by default, but I do have a solution!

Wrangler will create a directory in your project that has the worker files in it. Among other files there is an index.js file with the actual worker script in it.
On line 38 there is an if-statement that deals with reading assets from the Cloudflare KV store that looks something like this:

if (DEBUG) {
  // customize caching
  options.cacheControl = {
    bypassCache: true,
  }
}

This snippet of code controls the caching behaviour for debug mode. What we want to do is make sure that JSON files are not cached in the browser. This can be achieved by changing the cache control headers like so:

if (DEBUG) {
  // customize caching
  options.cacheControl = {
    bypassCache: true
  };
} else if (url.pathname.match(/json$/)) {
  options.cacheControl = {
    browserTTL: 1
  };
}

For some reason I couldn't get browserTTL: null or browserTTL: 0` to work properly. Setting it to 1 second works however.

The site now works properly. The JSON files are cached on the Cloudflare CDN but only for 1 second in the browser. This means that the service worker should now update properly.

Discuss on Twitter

Get the latest content in your inbox for free

Some of the things I write about

  • Self-hosting
  • Productivity
  • Ruby on Rails performance
  • News in the software development world

I care about the protection of your data. Read my  Privacy Policy.