service-workeramazon-cloudfrontcreate-react-appsw-precache

How to configure Service Worker with React to prevent Uncaught Syntax Error on new deployments at AWS CloudFront


I've been reading SO posts and Github issues for the past few days on this topic and I still can't seem to find a combination that works for my setup. Hoping that someone can point me to a specific solution. Here's what's going on.

I'm using create-react-app v2 with sw-precache. Builds go through CircleCI to push new files to S3, which are in turn served from CloudFront. The final step of the build is to invalidate the previous CloudFront distribution.

The problem I'm running into is when a new build is deployed and the service worker is updated, the next page load throws an error because the bundle files that are served by the service worker no longer exist. To say that again, I can load the site at www.example.com but if I then open a new tab and load www.example.com/test I get the Uncaught Syntax Error.

A few notes about my setup.

  1. I created a behavior in CloudFront to set Minimum and Maximum TTL for service-worker.js to 0.

  2. For my sw-precache-config.js, here's my setup:

module.exports = {
  staticFileGlobs: [
    'build/index.html',
    'build/static/css/**.css',
    'build/static/js/**.js'
  ],
  swFilePath: './build/service-worker.js',
  stripPrefix: 'build/',
  handleFetch: false,
  runtimeCaching: [...]
}
  1. When I load the first page after a build, for the index.html I see the following response: Status Code: 200 OK (from ServiceWorker)

My assumption is that I want the index.html file to not be cached by the service worker. But if I do that, won't I lose my offline capabilities? Should I set up a runtimeCaching for index.html to be networkFirst so that I can always ask for it but fall back to cache when offline? If so, would that look like this:

runtimeCaching: [
    urlPattern: '/index.html',
    handler: 'networkFirst'
]

Some of the things I've tried but haven't worked for me include showing a message to users to reload when this happens (technically works but user experience is not optimal). Also looked at skipWaiting: false option, but kept seeing the same error on new builds.


Solution

  • Your problem might be related to caching service-worker.js in user browsers, so when you deploy a new version, the old service-worker still cached on users browsers.

    Minimum and Maximum TTL for service worker file should not be 0. You should always cache it on Cloudfront edge since you can run invalidation requests to purge cloudfront edge cache after a new deployment.

    The problem might be related to the cache in users browsers. You can try to remove cache headers for service-worker.js files when uploading files to the bucket. You might want to see the diference between cache in CloudFront edge and cache on user browsers.

    I wrote an article talking that and how to deploy Single Page applications and troubleshot cache issues. Please have a look at: https://lucasfsantos.com/posts/deploy-react-angular-cloudfront/

    I also talk about sw-precaching on single page apps in the article:

    Service worker JavaScript update frequency (every 24 hours?), https://github.com/GoogleChromeLabs/sw-precache/issues/332