如何最好地从CloudFront提供版本化的S3文件?



我有一个CloudFront分布,其中有两个起源:一个起源是一个静态S3桶(由CloudFront缓存),另一个起源是一个动态服务器(不缓存)。当用户登录到我的应用程序时,动态源将用户重定向到静态的、缓存的S3桶源。

现在,我通过做以下事情来处理S3桶的版本控制:我在每个版本中将代码的版本附加到S3桶的路径上(因此,如果我的S3桶的路径通常是/static/ui,它现在变成/v1.2/static/ui)。CloudFront中S3桶的缓存行为路径模式为/static/ui,但S3桶的原始设置路径模式为/v1.2。不幸的是,由于原始路径不包含在我的缓存行为中,每当我必须将其更改为指向新版本时,我必须使缓存无效,以便CloudFront将检查新的原始路径。

所以,释放过程是这样的:

  1. 我创建了一个新版本的UI代码并将其添加到S3,并将该版本添加到我的S3桶的路径(创建一个看起来像/v1.2/static/ui的路径)。
  2. 我更改了我的"Origin path"值在CloudFront与我的S3起源相关联,在它有新的版本(所以它成为/v1.2)。这使得对我的CloudFront分发的所有请求都转发到我的原点,/v1.2前缀到原点路径。
  3. 我的CloudFront缓存无效

这种方法控制我的UI工作-但是有更好的方法吗?我希望能够处理版本控制我的S3桶,而不必在每次更改版本时使缓存无效。

我最终通过以下方式控制S3桶的版本并处理CloudFront缓存破坏:

  1. 我改变了Webpack构建静态资产的方式,除了我的index.html,我通过向Webpack构建的所有文件添加哈希,现在它指向我所有的哈希文件名。因此,例如,以前Webpack构建的给定JavaScript块称为12.js,现在可能称为0b2fb3071ad992833dd4.js,并且index.html现在引用新的散列文件名。文件哈希值是由文件中的内容生成的,如果文件中的内容发生变化,哈希值也会发生变化。
  2. 我确保当我的静态文件上传到S3时,index.html文件具有头Cache-Control: no-cache发送给我S3桶中的index.html文件的每个请求。这使得CloudFront永远不会缓存index.html文件,但仍然会缓存index.html指向的散列文件名。
  3. 我将我的静态文件的版本添加到我上传静态资产的S3桶的路径(例如,当我向我的index.html文件发出请求时,我的S3桶的路径可能看起来像/v1.2/static/ui/index.html)。
  4. 在每一个新版本,我更新我的CloudFront源路径为我的S3桶原点指向我的UI的新版本(所以它可能从/v1.2更改为/v1.3)。

因为我的index.html没有被CloudFront缓存,并且因为index.html点的所有其他静态文件都是散列的,并且在每次发布时会有不同的文件名(如果文件发生了变化),我不再需要在每次发布时手动发送CloudFront缓存无效到我的S3桶的路径,因为在每次发布时,index.html文件将指向全新的文件,这些文件将不会被缓存在CloudFront中,直到用户向它发出新的请求。

这也意味着切换我的CloudFront源路径现在将立即将用户切换到我的UI的不同版本,我不需要等待估计的5分钟手动CloudFront缓存失效生效。

最后,这种缓存破坏方法也适用于浏览器端缓存,所以我能够让保存在S3桶中的文件向用户发送Cache-Control: max-age=604800头文件,除了我的index.html文件,并为我的用户启用浏览器端缓存。当index.html指向其静态资产的新散列文件名时,浏览器端缓存无效。这大大提高了我的应用程序的性能。

这一切的代价是不能在CloudFront或用户的浏览器中缓存我的index.html文件,但我认为缓存这种方式的好处大于成本。

最新更新