在Express.js中,可以通过设置响应头来实现缓存控制。为了理解缓存控制的实现方式,我们需要了解两个重要的概念:ETag和Last-Modified。

  1. ETag(实体标签):ETag是一个用于标识资源版本的标签。服务器会为每个资源生成一个唯一的ETag,并在每个响应中发送给客户端。客户端可以在请求中的 If-None-Match标头 中将上一次收到的ETag发送回服务器。服务器可以比较这两个ETag值,以确定资源是否有新的版本可用。如果两个ETag匹配,表示资源没有变化,服务器可以返回一个304 Not Modified的响应,告诉客户端使用缓存版本。
  2. Last-Modified(最后修改时间):服务器会在响应中发送一个Last-Modified标头,指示资源的最后修改时间。客户端可以在后续请求中的 If-Modified-Since标头 中将上一次收到的最后修改时间发送回服务器。服务器可以比较这两个最后修改时间,以确定资源是否有新的修改。如果最后修改时间相同,表示资源没有变化,服务器可以返回一个304 Not Modified的响应。

下面是一个示例,展示了如何使用ETag和Last-Modified来实现缓存控制:

app.get('/api/data', (req, res) => {
  // 假设这是一些动态生成的数据
  const data = generateData();
 
  // 设置ETag和Last-Modified响应头
  const lastModified = new Date().toUTCString();
  const etag = generateETag(data);
 
  res.set('Last-Modified', lastModified);
  res.set('ETag', etag);
 
  // 检查客户端发送的If-None-Match和If-Modified-Since标头
  const ifNoneMatch = req.get('If-None-Match');
  const ifModifiedSince = req.get('If-Modified-Since');
 
  // 如果ETag和If-None-Match匹配,发送304 Not Modified响应
  if (ifNoneMatch === etag) {
    return res.sendStatus(304);
  }
 
  // 如果Last-Modified和If-Modified-Since相同,发送304 Not Modified响应
  if (ifModifiedSince && new Date(ifModifiedSince) >= new Date(lastModified)) {
    return res.sendStatus(304);
  }
 
  // 返回数据
  res.json(data);
});

在上面的例子中,我们使用res.set()方法设置了响应头Last-ModifiedETag,分别对应最后修改时间和实体标签。然后,我们获取请求中的If-None-MatchIf-Modified-Since标头,并与服务器生成的ETag和最后修改时间进行比较。

如果客户端发送的ETag与服务器生成的ETag匹配,或者客户端发送的最后修改时间大于等于服务器的最后修改时间,服务器将返回一个304 Not Modified的响应。

这样,通过使用ETag和Last-Modified来进行缓存控制,可以减少网络流量,提高应用程序的性能和响应速度。