3 分钟带你了解协商缓存和强缓存
老生常谈,今天聊一聊浏览器里的缓存机制。 协商缓存(Conditional Cache)和强缓存(Strong Cache)都是 HTTP 协议中的缓存机制,用于提高网页加载速度
- 强缓存:浏览器会根据缓存的响应头信息,判断缓存是否可用,如果可用则直接返回缓存内容,而不会向服务器请求数据
- 协商缓存:服务端根据请求头信息,判断浏览器缓存是否可用,如果可用继续使用浏览器缓存,不可用返回最新的数据
整体流程
字段说明
Cache-Control
这个字段决定浏览器和服务端的缓存策略,是 HTTP 1.1 引入的
-
no-store: 所有内容都不会被缓存到缓存或 Internet 临时文件中, 这里分两种情况
- 浏览器设置了 Cache-Control: no-store,服务端未设置时,走的是协商缓存逻辑。
graph LR A[请求] --> B[200] --> C[再次请求] --> D[304]- 服务端设置了 Cache-Control: no-store,浏览器不论是否设置,都会每次请求内容
graph LR A[请求] --> B[200] --> C[再次请求] --> D[200] -
no-cache: 强每次请求都会向服务器请求数据,走协商缓存逻辑。和上面
no-store里的第一种情况差不多 -
max-age=xxx: 指定缓存时间,超过时间后,缓存失效,下次请求会向服务器请求数据,走协商缓存逻辑。(实测下来,只有客户端设置了 max-age=0 才有用,此时客户端不会强缓存)
Pragma 和 Expires
- Pragma 和 Expires 都是 HTTP 1.0 的缓存控制字段,为了兼容老旧的服务器,仍然可以同时使用 Pragma 和 Cache-Control
- Pragma 的有效值为:no-cache, no-store。效果和 Cache-Control 一样
- Expires 表示内容的过期时间。如果客户端时间不准确,有可能会导致缓存失效,重新发送请求。估引入 Cache-Control:max-age=xxx。其实用户改变客户端时间,也是不影响缓存时间
整体流程解析
前提要求:通过前面字段说明,我们知道开启浏览器缓存条件
客户端请求头,不能设置缓存失效。比如
no-store, no-cache, max-age=0服务端设置了缓存时间。比如
Cache-Control: max-age=86400,或者Expires: Thu, 01 Jan 1970 00:00:00 GMT
-
发送
get请求,是否有缓存 -
有缓存,强缓存是否新鲜
判断规则,通过
Cache-Control: max-age=86400或者Expires: Thu, 01 Jan 1970 00:00:00 GMT,如果同时存在,cache-control 优先级高 -
如果缓存过期,发送请求询问服务端,走协商缓存
请求头中,会携带上一次响应里面的
Etag和Last-Modified。分别是if-none-match: 【Etag】和if-modified-since: 【Last-Modified】通过 etag 判断的准确性会高于通过修改时间
因为【修改时间】的缓存逻辑,在以下场景会有问题
- 服务端定时程序周期性修改文件修改时间,但是文件内容没有改变,导致缓存失效,发送请求
- 修改时间只能精确到秒,如果修改时间间隔小于秒,就会导致缓存失效,发送请求
浏览器和服务端如何设置缓存策略
- 浏览器设置缓存策略
<html>
<head>
<!--或者为其他合法值 content="max-age=86400"-->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<!-- 其他<head>中的内容 -->
</head>
</html>
- nginx 服务器设置缓存策略
http {
// 写在这里作用于全局
server {
location / {
// 添加响应头
add_header Cache-Control "max-age=3600";
root html/stable;
try_files $uri $uri/ /index.html;
}
}
}