如何使用 React 配置 Service Worker 以防止在 AWS CloudFront 的新部署中出现未捕获的语法错误

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

过去几天我一直在阅读有关此主题的 SO 帖子和 Github 问题,但我似乎仍然找不到适合我的设置的组合。希望有人能指出我具体的解决方案。这是正在发生的事情。

我正在使用带有 sw-precache 的 create-react-app v2。构建通过 CircleCI 将新文件推送到 S3,这些文件又由 CloudFront 提供。构建的最后一步是使之前的 CloudFront 分配失效。

我 运行 遇到的问题是,当部署新版本并更新 service worker 时,下一个页面加载会抛出错误,因为 service worker 提供的包文件不再存在。再说一遍,我可以在 www.example.com 加载站点,但如果我打开一个新选项卡并加载 www.example.com/test,我会收到未捕获的语法错误。

关于我的设置的一些注意事项。

  1. 我在 CloudFront 中创建了一个行为,将 service-worker.jsMinimum and Maximum TTL 设置为 0

  2. 对于我的 sw-precache-config.js,这是我的设置:

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. 当我在构建后加载第一页时,对于 index.html 我看到以下响应:Status Code: 200 OK (from ServiceWorker)

我的假设是我希望 index.html 文件不被 service worker 缓存。但是如果我那样做,我不会失去我的离线能力吗?我是否应该将 index.html 的 runtimeCaching 设置为 networkFirst 以便我可以随时请求它但在离线时回退到缓存?如果是这样,它看起来像这样吗:

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

一些我已经尝试但对我没有用的东西包括在发生这种情况时向用户显示一条消息以重新加载(技术上可行,但用户体验不是最佳的)。还查看了 skipWaiting: false 选项,但在新版本中不断看到相同的错误。

您的问题可能与在 用户浏览器 中缓存 service-worker.js 有关,因此当您部署新版本时,旧的 service-worker 仍然缓存在用户浏览器上。

服务工作者文件的最小和最大 TTL 不应为 0。您应该始终将其缓存在 Cloudfront 边缘,因为您可以 运行 在新部署后清除云端边缘缓存的无效请求。

问题可能与 用户浏览器 中的缓存有关。将文件上传到存储桶时,您可以尝试删除 service-worker.js 文件的缓存 headers。您可能希望了解 CloudFront 边缘缓存与用户浏览器缓存之间的区别。

我写了一篇文章讨论这个问题以及如何部署单页应用程序和解决缓存问题。请看一下:https://lucasfsantos.com/posts/deploy-react-angular-cloudfront/

我在文章中也谈到sw-precaching单页应用:

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