Offline capable Gatsby site on Cloudflare Workers
Learn how to get a Gatsby site to work properly on Cloudflare Workers. You can get your site loading in under 20ms and it will work offline as well.
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.