配置 HTTP 缓存行为

此 Codelab 介绍了如何更改运行 Express 服务框架的基于 Node.js 的 Web 服务器返回的 HTTP 缓存标头。以及如何使用 Chrome 开发者工具中的“Network”面板来确认预期的缓存行为是否确实得到了应用。

熟悉示例项目

以下是您将在示例项目中使用的关键文件:

  • server.js 包含提供 Web 应用内容的 Node.js 代码。它使用 Express 来处理 HTTP 请求和响应。需要特别指出的是,express.static() 用于传送公共目录中的所有本地文件,因此 serve-static 文档会很方便。
  • public/index.html 是 Web 应用的 HTML。与大多数 HTML 文件一样,该文件的网址中不包含任何版本编号信息。
  • public/app.15261a07.jspublic/style.391484cf.css 是 Web 应用的 JavaScript 和 CSS 资源。每个这些文件的网址中都包含与其内容相对应的哈希值。index.html 负责跟踪要加载的特定版本化网址。

为 HTML 配置缓存标头

在响应针对不包含版本控制信息的网址的请求时,请务必在响应消息中添加 Cache-Control: no-cache。除此之外,建议另外设置以下两个响应标头中的一个:Last-ModifiedETagindex.html 就属于这一类别。这一过程可以分为两个步骤。

首先,Last-ModifiedETag 头文件由 etaglastModified 配置选项控制。实际上,对于所有 HTTP 响应,这两个选项都默认设置为 true,因此,在当前设置中,您无需选择启用即可获取该行为。但您仍然可以在配置中明确指定值。

其次,您需要能够添加 Cache-Control: no-cache 标头,但仅限于 HTML 文档(在本例中为 index.html)。有条件地设置此标头的最简单方法是编写自定义 setHeaders function,并在其中检查传入的请求是否为 HTML 文档。

  • 点击 Remix to Edit 使项目可修改。

server.js 中的静态服务配置按以下方式开始:

app.use(express.static('public'));
  • 进行上述更改,最终结果应如下所示:
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    }
  },
}));

为版本化网址配置缓存标头

在响应针对包含“fingerprint”或版本控制信息的网址的请求,并且这些网址的内容绝不会更改时,请在响应中添加 Cache-Control: max-age=31536000app.15261a07.jsstyle.391484cf.css 就属于此类别。

以上一步中使用的 setHeaders function 为基础,您可以添加额外的逻辑来检查给定请求是否针对的是版本化网址,如果是,则添加 Cache-Control: max-age=31536000 标头。

要做到这一点,最可靠的方法是使用正则表达式来查看所请求的资源是否与已知哈希所属的特定模式相匹配。就此示例项目而言,始终是一组数字 0-9 中的 8 个字符以及小写字母 a-f(即十六进制字符)。哈希的两侧始终用 . 字符分隔。

与这些通用规则匹配的正则表达式可以表示为 new RegExp('\\.[0-9a-f]{8}\\.')

  • setHeaders 函数修改为如下所示的内容:
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    const hashRegExp = new RegExp('\\.[0-9a-f]{8}\\.');

    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    } else if (hashRegExp.test(path)) {
      // If the RegExp matched, then we have a versioned URL.
      res.setHeader('Cache-Control', 'max-age=31536000');
    }
  },
}));

使用开发者工具确认新行为

对静态文件服务器完成修改后,您可以检查并确保已设置正确的标头,方法是在打开开发者工具的 Network 面板的情况下预览实时应用。

  • 如需预览网站,请按查看应用,然后按全屏 全屏

  • 通过右键点击列标题,可自定义“网络”面板中显示的列,以包含最相关的信息:

配置开发者工具的“Network”面板。

在这里,需要注意的列是 NameStatusCache-ControlETagLast-Modified

  • 打开开发者工具并打开“Network”面板,然后刷新页面。

页面加载后,您应该会在“Network”面板中看到如下所示的条目:

“网络”面板列。

第一行对应于您导航到的 HTML 文档。这是通过 Cache-Control: no-cache 正确提供的。该请求的 HTTP 响应状态为 304。这意味着浏览器知道不会立即使用缓存的 HTML,而是使用 Last-ModifiedETag 信息向网络服务器发出 HTTP 请求,以查看其缓存中已包含的 HTML 是否有任何更新。HTTP 304 响应表示没有更新的 HTML。

接下来两行显示的是有版本控制的 JavaScript 和 CSS 资源。您应该会看到它们通过 Cache-Control: max-age=31536000 传送,并且每个请求的 HTTP 状态为 200。由于所使用的配置,系统没有向 Node.js 服务器发出实际请求,点击条目将显示更多详细信息,包括响应来自“(来自磁盘缓存)”。

网络响应状态 200。

ETag 和 Last-Modified 列的实际值无关紧要。重要的是确认它们是否进行了设置。

总结内容

完成此 Codelab 中的步骤后,您现在已熟悉了如何使用 Express 在基于 Node.js 的 Web 服务器中配置 HTTP 响应标头,以充分利用 HTTP 缓存。此外,您还需要通过 Chrome 开发者工具中的“Network”面板,确认系统是否使用了预期的缓存行为。