S3 + Cloudfront 上的浏览​​器缓存破坏

Posted

技术标签:

【中文标题】S3 + Cloudfront 上的浏览​​器缓存破坏【英文标题】:Browser Cache Busting on S3 + Cloudfront 【发布时间】:2018-09-02 13:18:17 【问题描述】:

我在 S3 + Cloudfront 上托管了一个静态网站。要重新部署,我上传静态文件

aws s3 sync static

并使云端缓存失效

aws cloudfront create-invalidation

在我更新这些新资源后,强制浏览器获取这些新资源的推荐方法是什么?问题是浏览器正在缓存这些资产,而用户正在使用旧(无效)版本的脚本、图像和样式。

【问题讨论】:

【参考方案1】:

通常,您可以执行多个步骤来确保您的 AWS CloudFront 和 S3 设置为在新部署时缓存失败。

确保使 index.html 的缓存无效(如果已缓存) 您可以为 javascript、CSS 等静态资产设置查询参数或新文件名。

使用新文件名

<!doctype html>
<html lang="en">
  <head>
     <link href="styles.h2d1f722.css" rel="stylesheet" />
  </head>
  <body>
     <script type="text/javascript" src="scripts.cbe3c974.js"></script>
  </body>
</html>

您可以使用前端构建工具(例如 Webpack、Gulp 等)生成新文件名

使用查询参数

<!doctype html>
<html lang="en">
  <head>
     <link href="styles.css?hash=h2d1f722" rel="stylesheet" />
  </head>
  <body>
     <script type="text/javascript" src="scripts.js?hash=cbe3c974"></script>
  </body>
</html>

设置查询参数时,请确保您已在 CloudFront 中启用(否则将返回文件的缓存响应)。

注意:比较这两种方法,它们各有优缺点。具有相同的文件名,您可以使用 S3 本机版本控制对文件进行版本控制,同时拥有新名称,这样做没有多大意义,因为新部署会为文件添加新名称。除非您删除旧文件或将旧文件移动到另一个存储桶,否则还有新文件名会使 S3 存储桶变得杂乱无章。

确保 index.html 中有适当的值 Meta 标记(Cache-Control、Expires 和 Pragma 标头)。

使用元标记

<!doctype html>
<html lang="en">
  <head>
     <meta http-equiv="cache-control" content="max-age=0" />
     <meta http-equiv="cache-control" content="no-cache" />
     <meta http-equiv="expires" content="0" />
     <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
     <meta http-equiv="pragma" content="no-cache" />
     <link href="styles.css?hash=h2d1f722" rel="stylesheet" />
  </head>
  <body>
     <script type="text/javascript" src="scripts.js?hash=cbe3c974"></script>
  </body>
</html>

在这个例子中,它指示不要在浏览器缓存。但是,您可以为这些设置适当的值。

为静态资产实施版本控制方案,这样即使将旧版本的 index.html 提供给最终用户(从浏览器缓存),网页仍然会加载旧资产(JS、CSS 等) .) 没有任何问题。

【讨论】:

嗨@Ashan,我也在为此苦苦挣扎。 S3 中的元数据道具呢?有了这些标头,它们还需要吗? 所以 CloudFront 会读取 HTML 文件内容以找出要应用于每个文件的缓存策略? @CarlosDelgado 很抱歉让您感到困惑(我已删除之前的评论)。有两个级别的缓存。 1) 在 CloudFront 边缘缓存 2) 在浏览器级缓存 对于 1) CloudFront 中的 TTL 配置适用,对于 2) Index.html 元标记和 S3 元数据(其中一些)适用。 嗨@Ashan,感谢您的澄清。我觉得值得一提的是,这里还有更多的选择,在这里都有很好的解释:docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…【参考方案2】:

如果浏览器已经保存了缓存值,则不能强制远程浏览器,除非手动干预。

你需要追加

script.something.js?buildid=someuniquereference

并让 cloudfront 不在查询字符串参数上缓存。

您还可以包含 filename.hash.js 或 filename.hash.html 和 index.html / 默认文档,使用缓存控制标头减少缓存时间。

这样,如果您进行任何更改,您可以更改该数字,缓存也会在客户端上被破坏。

但是一旦你发送了缓存头,你就无法远程清理浏览器上的客户端缓存了。

希望对你有帮助。

【讨论】:

如何告诉浏览器不要在 S3 + Cloudfront 上缓存资产? @Will 在script.something.js?buildid=someuniquereference,每次构建都会改变一些独特的引用,每当您构建新资产时,这将强制浏览器从云端重新加载资产,并且您已经创建了无效云端将服务新内容。 所有浏览器都尊重查询字符串参数吗? 是的。 ***.com/questions/9692665/cache-busting-via-params 请注意,官方的解决方案是在您希望 S3 忽略的查询字符串参数上使用 x- 前缀,即使他们的 API 引入了新的恐惧。服务会误解某些前缀,例如taggingselect,因为它假定您正在尝试访问子资源,而不是对象......所以例如x-buildid=... 可能是一个更加面向未来的任意键选择。

以上是关于S3 + Cloudfront 上的浏览​​器缓存破坏的主要内容,如果未能解决你的问题,请参考以下文章

如何使 CloudFront 永远不会在 S3 存储桶上缓存 index.html

在cloudFront中混淆了最小,最大和默认TTL

Apple 在 S3 上的 apple-app-site-association 文件与 CloudFront 分发

AWS cloudfront 不更新 S3 中的文件更新

没有 S3 存储桶的 AWS Cloudfront CORS 标头

markdown s3 CloudFront清理缓存,使对象失效(仅Web分配)