最近在学习网站性能优化相关的内容,关于网站优化点特别多而 HTTP 缓存也是比较重要的一部分,于是今天就着重看下 HTTP 缓存相关的内容加深下对此相关知识的理解和认识。自己动手通过简单的服务,看看其中的过程。

# 1.ETag 验证缓存的响应

在本地通过 express 启了一个非常简单的个服务,具体如下

// app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.send('hello http')
})
app.listen(3000, () => {
  console.log('The server is running at http://127.0.0.1:3000/')
})

但是仔细看却发现,第一次进入页面 http://127.0.0.1:3000 / 时,Status 为 200 而再次刷新发现 Status 却是 304

仔细对比发现

  1. 第一次请求时候请求参数中并没有 If-None-Match 字段但是却有个 Pragma;同时在请求的 Response 中有一个 <font style="color:red">ETag: W/"a-QFZ79AprHeNlMfPMKXyEUV+lyOg"</font > 字段。
  2. 刷新页面后再次请求在请求头中却有个 <font style="color:red">If-None-Match: W/"a-QFZ79AprHeNlMfPMKXyEUV+lyOg"</font> ,If-None-Match 的值和第一次请求的 ETag 的值相同。

经过查询才了解原理浏览器会根据 HTTP 请求的 ETag 验证请求的资源是否发生了改变,如果它未发生变化,服务器将返回 “304 Not Modified” 响应,并且资源从浏览器缓存中读取,这样就不必再次下载请求。
由此看来整个的过程就是下面这样:

  1. 如果缓存中有 ETag 令牌,客户端请求时会自动在 “If-None-Match” HTTP 请求标头内提供 ETag 令牌。
  2. 服务器根据当前资源核对令牌,验证是否发生变化,将验证结果通知给客户端,客户端根据结果看看是否需要从缓存中读取还是发送资源请求。

补充一个很直白的 TCP 协议的三次握手 的理解。
为了验证查证的结果,我又添加一个请求处理。这个过程是,客户端明确返回一个 ETag, 但是这里每次请求的的返回值都不相同,这里简单的使用了个 etag++。

// app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.send('hello http');
})
// 验证 ETag
let etag = 0;
app.get('/test', (req, res) => {
  etag++;
  res.set('ETag', etag);
  res.send('ETag');
})
app.listen(3000, () => {
  console.log('The server is running at http://127.0.0.1:3000/')
})

image.png

查看下 /test 地址的请求结果,会发现 If-None-Match 的值和 Response 中的 ETag 值每次都不相同,并且是 浏览器会将每次的 ETag 值都缓存起来在下次请求的时候发送给服务器。这样一来,每次服务器每次校验的值都是不相同的,所以这种就没有做缓存,因此每次请求 /test 地址都是 200 的状态。
示例源码地址