最大化缓存命中率

提高网店性能的最佳方法之一是最大化缓存命中率。任何可以从 Managed Runtime(托管运行时)的 CDN 缓存技术中完成的请求都算作缓存命中。随着每次缓存命中,您可以加快用户的页面加载速度,因为您节省了在服务器端渲染该页面以及向后端系统和 API 发出任何请求的成本。

本指南涵盖最大化缓存命中率的三种不同技术:设置最佳缓存有效周期、条件渲染和过滤查询字符串。我们来详细介绍每种技术。

缓存 HTTP 请求的最佳时间取决于请求的内容。加载很少更改的内容页面的请求可以安全地缓存很长时间。相比之下,经常使用新产品进行更新的产品列表页面可能需要较短的缓存有效期,例如 15 分钟。尽可能选择较长的缓存有效周期,以最大限度地提高缓存命中率。

HTTP 响应中的缓存控制标头确定对页面请求的响应存储在 CDN 缓存中的时间长度。PWA Kit 项目中页面响应的缓存有效周期默认为 600 秒(或 10 分钟)。您可以逐页自定义缓存有效周期,也可以为所有页面进行自定义。

要整体了解有关缓存的更多信息,我们推荐 Google 的这篇文章:Prevent unnecessary network requests with the HTTP Cache(使用 HTTP 缓存防止不必要的网络请求)。

任何页面组件的 getProps 函数都允许您使用在调用 res 中传入的对象自定义 HTTP 响应。要设置页面的缓存有效周期,请使用 res 对象的 set 方法设置 Cache-Control 标头并为 max-age 指令指定以秒为单位的值。

例如,此 ProductList 组件将缓存有效周期从默认的 600 秒延长到 900 秒:

我们不建议您在属于 app/components/_app/index.jsx 中定义的 App 特殊组件的 getProps 函数中设置缓存控制头。App 组件和当前页面组件的 getProps 函数同时执行。如果在两个函数中设置相同的响应标头,这种并行执行会导致不可预知的结果。

您可以在 app/ssr.js 中设置所有页面的缓存有效周期。您可以通过为 defaultCacheTimeSeconds 设置新值来更改默认缓存有效周期。如果您需要对 HTTP 标头进行更细粒度的控制,请添加设置自定义标头的 Express 处理程序,如下所示:

您可以通过使用 Chrome 的网络选项卡中的 DevTools 检查您的网络请求,来测试响应标头是否存在缓存控件。或者,您可以在终端中运行以下 curl 命令,该命令会输出所有响应标头。在示例命令中将 <URL> 替换为您要测试的完整 URL,包括任何必需的查询字符串。

为确保页面适合 CDN 缓存,您必须添加条件代码以避免在服务器端渲染以下类型的内容:

  • 个性化内容,例如用户名、购物车中的商品数量和首选付款方式。个性化内容不适合单个用户以外的任何人,并且与任何其他人无关。缓存单个用户的响应不会增加缓存命中。
  • 经常更改的内容,例如产品价格、剩余库存或促销活动。此内容不适合缓存,因为当页面包含已经过时的信息时,用户可能会感到困惑。

将在服务器端呈现的页面视为客户端构建的通用基础。在将页面的服务器端版本快速加载到用户的设备上后,浏览器会接管以呈现个性化且经常变化的内容。

要确定渲染发生在客户端还是服务器端,请检查是否存在 window 对象,该对象仅存在于客户端。以下示例使用此技术仅在客户端呈现价格:

要在浏览器中预览在服务器端呈现的页面版本,请附加到 ?__server_only URL。此查询参数停止 hydration 进程,以使浏览器不会接管渲染,在服务器端渲染之后页面保持不变。

大多数网店应用程序使用 URL 的查询字符串来存储代表应用程序状态各个方面的参数和值。例如,当用户搜索“sweaters”时,您可以在查询字符串中包含搜索词:?search=sweaters。查询字符串也常用于跟踪用户操作。例如,我们可以将唯一的查询字符串附加到电子邮件中的每个链接以跟踪与它的交互:user=juanita&source=email

在缓存方面,并非所有查询字符串参数都是相关的。Managed Runtime 包含称为请求处理器的边缘函数,允许您在查找缓存响应之前修改请求的查询字符串。您可以通过使用请求处理器将相似的 URL 映射到相同的缓存响应来增加缓存命中。

要自定义请求处理器,请编辑 app/request-processor.js 中定义的 processRequest 函数。

以下示例定义从查询字符串中过滤掉参数 gclidutm_campaign 的请求处理器。这些参数通常与 Google 营销活动相关联,并且仅在客户端有用。为了简化查询字符串的使用,它从 PWA Kit React SDK 导入 QueryParameters 类。

用于在缓存中查找相应对象的完整 URL 包括请求处理器返回的查询字符串的版本。如果没有为该 URL 缓存响应,则此 URL 的相同修改版本将传递给 Express 应用程序。

使用这种方法时要注意两个问题:

首先,确保您的应用不依赖任何过滤参数进行渲染!例如,如果您从上面过滤 search 参数,您将很难显示正确的搜索结果。

其次,从您希望重定向的请求中过滤参数时要小心。如果您的代码无法访问过滤参数,则该参数也不能用于重定向。考虑请求主页组件,它将 www.example.com?lang=en 的请求重定向到特定区域设置的路径,例如 www.example.com/en。如果过滤掉 lang 参数,您将无法重定向到正确的区域设置。

考虑这个序列:

  1. 请求处理器处理 www.example.com/?gclid=123 的请求。
  2. 请求处理器过滤 gclid 查询字符串参数。
  3. 该请求将使用完整的 URL www.example.com 转发到应用程序。
  4. 应用程序将重定向返回至 www.example.com/en

请注意,在最后一步中,我们丢失了 gclid 原始参数,因此在用户被重定向后,浏览器将无法使用此参数。要解决此挑战,请避免过滤您希望重定向的请求的查询字符串。

现在您已知道如何使用各种技术来提高页面请求的缓存命中率。

阅读我们的代理请求指南,了解缓存 API 请求和代理的其他好处。