此 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.js
和public/style.391484cf.css
是 Web 应用的 JavaScript 和 CSS 资源。这些文件的网址中都包含一个与其内容对应的哈希。index.html
负责跟踪要加载的特定版本网址。
为 HTML 配置缓存标头
在响应针对不含版本信息的网址的请求时,请务必在响应消息中添加 Cache-Control: no-cache
。此外,建议您设置以下两个响应标头之一:Last-Modified
或 ETag
。index.html
属于此类别。您可以将其分解为两个步骤。
首先,Last-Modified
和 ETag
标头由 etag
和 lastModified
配置选项控制。实际上,这两个选项对于所有 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=31536000
。app.15261a07.js
和 style.391484cf.css
属于此类别。
基于上一步中使用的 setHeaders function
,您可以添加其他逻辑来检查给定请求是否针对版本化网址,如果是,则添加 Cache-Control:
max-age=31536000
标头。
最可靠的方法是使用正则表达式,查看请求的资源是否与您知道哈希属于的特定模式匹配。对于此示例项目,该字符串始终由 0-9 和小写字母 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');
}
},
}));
使用 DevTools 确认新行为
对静态文件服务器进行修改后,您可以打开 DevTools 中的“Network”面板,预览实时应用,以确保设置了正确的标头。
如需预览网站,请按 View App(查看应用)。然后按 Fullscreen(全屏)。
如需自定义“网络”面板中显示的列以包含最相关的信息,请右键点击列标题:
此处,需要注意的列是 Name
、Status
、Cache-Control
、ETag
和 Last-Modified
。
- 在 DevTools 中打开“网络”面板,然后刷新页面。
页面加载完毕后,您应该会在“Network”面板中看到如下所示的条目:
第一行是您导航到的 HTML 文档。此类资源会通过 Cache-Control: no-cache
正确提供。该请求的 HTTP 响应状态为 304
。这意味着,浏览器知道不应立即使用缓存的 HTML,而是使用 Last-Modified
和 ETag
信息向 Web 服务器发出 HTTP 请求,以查看其缓存中已有的 HTML 是否有任何更新。HTTP 304 响应表示没有更新的 HTML。
接下来的两行用于版本化 JavaScript 和 CSS 资源。您应该会看到它们是使用 Cache-Control: max-age=31536000
提供的,并且每个的 HTTP 状态均为 200
。由于所使用的配置,系统不会向 Node.js 服务器发出实际请求,点击该条目会显示更多详细信息,包括响应来自“(from disk cache)”。
ETag 和 Last-Modified 列的实际值没有太大影响。重要的是确认这些参数是否已设置。
总结
完成此 Codelab 中的步骤后,您现在已经熟悉了如何使用 Express 在基于 Node.js 的 Web 服务器中配置 HTTP 响应标头,以便最佳地使用 HTTP 缓存。您还可以通过 Chrome DevTools 中的“Network”面板,按照相关步骤确认是否使用了预期的缓存行为。