如何使 CloudFront 从不在 S3 存储桶上缓存 index.html

How to make CloudFront never cache index.html on S3 bucket

我有一个托管在 S3 存储桶上的 React 应用程序。使用 yarn build 缩小代码(这是一个基于 create-react-app 的应用程序)。 build 文件夹类似于:

build
├── asset-manifest.json
├── favicon.ico
├── images
│   ├── map-background.png
│   └── robot-icon.svg
├── index.html
├── js
│   ├── fontawesome.js
│   ├── packs
│   │   ├── brands.js
│   │   ├── light.js
│   │   ├── regular.js
│   │   └── solid.js
│   └── README.md
├── service-worker.js
└── static
    ├── css
    │   ├── main.bf27c1d9.css
    │   └── main.bf27c1d9.css.map
    └── js
        ├── main.8d11d7ab.js
        └── main.8d11d7ab.js.map

我从不希望 index.html 被缓存,因为如果我更新代码(导致 main.*.js 中的十六进制后缀更新),我需要用户下次访问时获取 <script src> 更改 index.html 以指向更新后的代码。

在 CloudFront 中,我似乎只能排除路径,排除“/”似乎无法正常工作。我在更改代码时遇到了奇怪的行为,如果我点击刷新,我会看到它,但如果我退出 Chrome 并返回,我会因为某种原因看到非常过时的代码。

我不想在每次代码发布时都触发失效(通过 CodeBuild)。还有别的办法吗?我认为挑战之一是因为这是一个使用 React Router 的应用程序,我不得不通过将错误文档设置为 index.html 并强制 HTTP 状态 200 而不是 403 来做一些技巧。

如果您不想 index.html 被缓存,请仅在该文件上设置 Cache-Control: max-age=0 header。 CloudFront 将在 每个 请求时向您的原始 S3 存储桶发出请求,但听起来这是需要的行为。

如果您想设置更长的到期时间并手动使 CloudFront 缓存失效,您可以使用 */* 作为失效路径(而不是 /有提到)。然而,全球所有 CloudFront 边缘节点最多可能需要 15 分钟才能反映您源中的更改。

这是我 运行 在将新文件上传到 s3 并使 Cloudfront 无效后对我的 index.html 文件设置缓存控制的命令:

aws s3 cp s3://bucket/index.html s3://bucket/index.html --metadata-directive REPLACE --cache-control max-age=0 --content-type "text/html"

基于CloudFront配置的解决方案:

转到您的 CloudFront 分配,在 "Behavior" 选项卡下并创建一个新行为。 指定以下值:

  • 路径模式:index.html
  • 对象缓存:自定义
  • 最大 TTL:0(或另一个非常小的值)
  • 默认 TTL:0(或另一个非常小的值)

保存此配置。

CloudFront 将不再缓存 index.html

在每次发布时 运行 使 index.html 失效比破坏 Cloudfront 的目的并每次从 S3 提供它(基本上是您的应用程序的入口点)要好得多。