爱你的缓存 ❤️

用户再次加载您的网站将使用其 HTTP 缓存,因此请务必 就会很好用

此博文是“Love your cache”视频( 2020 年 Chrome 开发者峰会上的内容。请务必观看视频

当用户再次加载您的网站时,他们的浏览器将使用 以便加快加载速度但对于本地存储的 网络可以追溯到 1999 年,其定义非常宽泛, 是否可能会再次从网络中抓取某个文件(例如 CSS 或图片) 与从缓存中加载相比,有点不精确。

在这篇博文中,我将介绍一种合理的新型缓存默认设置 实际上根本不执行缓存。但这只是默认设置 请继续阅读!

目标

当网站第二次加载时,您有两个目标:

  1. 如果您的用户安装的是最新版本, 如果您更改了某些内容,相应更改应该很快就会
  2. 执行第 1 步操作,同时尽可能少地从网络中提取数据

从最宽泛的意义上讲,您只需要向客户发送最小的更改 再次加载您的网站时合理设计网站结构以确保 如何有效分配任何变化并非易事(下文将对此进行详细介绍, 视频)。

不过,在考虑缓存时,您还有其他选择,或许 您决定让用户的浏览器 HTTP 缓存在您的网站上保留很长时间 因而根本无需发出网络请求或者 之前构建了一个 Service Worker, 检查其是否为最新版本。这是一种极端方式, 许多离线优先的类应用网络体验,但网络并不需要 或甚至完全依赖于网络。

背景

作为网络开发者,我们都习惯于“缓存过时”的想法。 但我们知道,解决这个问题的可用工具几乎是本能的: 刷新”或打开一个无痕式窗口,或使用浏览器的某种浏览器 开发者工具清除网站数据。

互联网上的普通用户没有同样的奢侈品。因此,当我们 有一些核心目标,那就是确保我们的用户 加载时,确保广告不会出现糟糕或 卡住了。(如果您想听听我介绍 web.dev/live 网站几乎被卡住了!)

有一些背景信息,这是导致“缓存过时”的一个常见原因实际上是 1999 年默认缓存。它依赖于 Last-Modified 标头:

<ph type="x-smartling-placeholder">
</ph> 显示不同资源由用户浏览器缓存多长时间的示意图
在不同时间生成的资源(显示为灰色)将缓存 因此第二次加载可以组合使用缓存的资源和最新资源

您加载的每个文件都会额外保留 10% 的当前生命周期,因为 浏览器就能看到它。例如,如果 index.html 是在一个月前创建的, 浏览器会再缓存三天左右

这在当时是出于善意的想法,但考虑到 集成的性质;这种默认行为意味着 这样用户就会有专为不同应用版本而设计的文件 (例如,星期二发布的 JS,以及星期五 发布),这都是因为这些文件并非同时更新。

光线充足的路径

现代的缓存默认设置是实际上不进行缓存 CDN:让您的内容更顺畅 。用户每次加载您的网站时,都会转到广告网络 看看它是否是最新版本。此请求的延迟时间较短 由在地理位置上靠近每个最终用户的 CDN 提供。

您可以使用此标头配置您的网站主机,以响应网络请求:

Cache-Control: max-age=0,must-revalidate,public

基本上就是这样此文件始终有效,您必须验证 然后才能再次使用它(否则 “建议”)。

就传输的字节数而言,此验证过程的成本相对较低(如果 未更改时,您的浏览器会收到一个小型 304 响应,但这会产生延迟,因为用户必须前往网络查找 。这也是这种方法的主要缺点。它在很大程度上可以 并且您选择的 CDN 具有 覆盖率较高,但对于移动网络速度较慢的用户 或使用不佳的基础设施。

无论如何,这都是一种现代方法 是热门 CDN(Netlify)上的默认配置 但几乎可以在任何 CDN 上配置。对于 Firebase Hosting,您可以 此标题 在“Hosting”部分 您的 firebase.json 文件中的名称:

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

因此,虽然我仍然建议将它作为合理的默认设置,但这只是默认操作! 请继续阅读下文,了解如何开始使用和升级默认设置。

具有指纹的网址

通过在资源、图片等的名称中包含文件内容的哈希值 那么可以确保这些文件始终 content,例如,这会产生名为 sitecode.af12de.js 的文件。时间 您的服务器会响应对这些文件的请求,那么,您可以放心地指示 最终用户的浏览器将其缓存起来很长时间 标头:

Cache-Control: max-age=31536000,immutable

此值为年份(以秒为单位)。根据相关规范,这实际上是 设为“永久”。

重要的是,不要手动生成这些哈希,因为手动工作量很大!您 可以使用 Webpack、Rollup 等工具来帮助您解决此问题确保 如需详细了解这些工具,请参阅工具报告

请注意,不仅仅是 JavaScript 可以从指纹网址受益; 而图标、CSS 和其他不可变数据文件等资源也可以采用如下名称: 。(请务必观看上面的视频,了解有关代码的更多信息 拆分,从而在网站发生变化时减少代码数量。)

无论您的网站采用何种方式进行缓存,这些 文件对于您可能构建的任何网站都极具价值。大多数网站仅 不会在每次发布时都发生变化

当然,我们不能以这种方式重命名面向用户的“友好”页面: index.html 文件复制到 index.abcd12.html,这不可行,您无法确定 用户每次加载您的网站时都会转到一个新网址!这些“友好的”网址 无法以这种方式重命名和缓存,这使我发现了一种可能的中间问题 。

中场

在缓存方面,显然有中立空间。我已 提供了两种极端方案:neverforever 缓存。而且, 是您可能希望缓存一段时间的一些文件,例如 “友好”上述网址

如果您希望缓存这些“易用”网址及其 HTML,建议您 考虑它们包含哪些依赖项、如何缓存它们以及如何 缓存一段时间可能会影响您。我们来看一个 HTML 网页 包含如下图像:

<img src="/images/foo.jpeg" loading="lazy" />

如果您通过删除或更改这个延迟加载项来更新或更改网站 图片,那么用户在查看您的 HTML 缓存版本时,可能会收到不正确或 缺少图片,因为它们在处理时仍缓存了原始 /images/foo.jpeg 再次访问您的网站

如果你要谨慎,这可能不会影响你。但从广义上来讲, 请注意,最终用户在缓存您的网站时,您的网站已不只是 您的服务器。相反,它可能以片段的形式存在于最终用户的缓存中。 。

一般来说,大多数有关缓存的指南都会介绍这种 - 您想缓存一小时、几小时,等等。要设置此选项, 可以使用这样的标头(缓存 3600 秒或一个 小时):

Cache-Control: max-age=3600,immutable,public

最后一点。如果您要制作的内容比较及时 例如新闻报道! 您应使用上面的合理默认设置。我们经常 如果用户希望始终查看最新数据, 和精彩的内容,例如有关新闻报道或时事 事件。

非 HTML 选项

除了 HTML,还有一些其他选项,适用于位于中间区域的文件 包括:

  • 一般情况下,寻找不会影响其他素材资源的素材资源

    • 例如:避免使用 CSS,因为这会改变 HTML 的显示方式 呈现
  • 在及时报道中使用的大图片

    • 您的用户很可能不会再访问任何一篇文章了 因此请不要永久缓存照片或主打图片 废物仓储
  • 代表自身有生命周期的事物的资产

    • 关于天气的 JSON 数据可能每小时只会发布一次, 则可以将上一条结果缓存一小时 - 该结果不会在您的窗口中发生变化
    • 开源项目的构建可能会受到速率限制,因此缓存一个 构建状态映像,直到状态可能会发生变化为止

摘要

当用户再次加载您的网站时,您已进行一次投票, 信心 - 他们希望再次回访,看到您提供的更多产品或服务。目前 但这并不总是会缩短加载时间 有多种选项可用,以确保您的浏览器只完成 需要同时提供快速且最新的体验。

缓存在 Web 上并不是一个新概念, 默认 - 请考虑使用一种并强烈选择采用更好的缓存策略 供您在需要时使用。感谢您阅读本邮件!

另请参阅

有关 HTTP 缓存的一般指南,请参阅 使用 HTTP 缓存防止不必要的网络请求