- HTTP浏览器缓存
- 服务器缓存/代理服务器缓存
- HTML缓存(本地缓存)/离线缓存ServiceWorker
- 【强缓存】浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器
- 【协商缓存】当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源
HTTP 缓存只能存储 GET 响应 当浏览器对某个资源的请求命中了强缓存时,返回的http状态为200(chrome会标有from-cache标记)
浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,拿出它的Expires跟当前的请求时间比较,如果请求时间在Expires指定的时间之前,就能命中缓存,否则就不行 如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。 缺点:【客户端时间不正确】由于它是服务器返回的一个绝对时间,在服务器时间与客户端时间相差较大时,缓存管理容易出现问题,比如随意修改下客户端时间,就能影响缓存命中的结果
- no-cache(请求头/响应头) (相当于强制使用协商缓存)强制所有缓存了该响应的缓存用户,在使用已存储的缓存数据前,发送带验证器的请求到原始服务器
- no-store(请求头/响应头) (相当于强制禁用缓存)缓存不应存储有关客户端请求或服务器响应的任何内容
- max-age=(请求头) 表示资源能够被缓存(保持新鲜)的最大时间,一般以秒为单位
- public(响应头) 表示该响应可以被任何中间代理(例如CDN)缓存。
- privatec(响应头) 表示该响应是专用于某单个用户的,中间代理不能缓存此响应,该响应值用于浏览器私有缓存
- must-revalidatec(响应头) 缓存在考虑使用一个陈旧的资源时,必须先验证它的状态,已过期的缓存将不被使用
通过web服务器返回的响应头中添加Expires和Cache-Control(一般服务器程序会有相应的api) 通过服务器专门的配置文件,配置expires和cache-control
当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回的 http状态为304并且会显示一个Not Modified的字符串 协商缓存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】这两对Header来管理的。
服务器会检查If-Modified-Since时间是否过期,如果未过期则返回304,过期服务器会返回200并更新Last-Modified时间 浏览器器会在重新加载的时候更新Last-Modified Header,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值 缺点:【客户端时间不正确】 由于Last-Modified与If-Modified-Since都是根据服务器时间返回的header,一般来说,如果篡改客户端缓存的情况下,这两个header配合起来管理协商缓存是不可靠的
ETagHTTP响应头是资源的特定版本的标识符。当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器 当下次再次向服务器请求A时,会通过类似 If-None-Match: "3f80f-1b6-3e1cb03b" 的请求头把ETag发送给服务器,服务器再次计算A的哈希值并和浏览器返回的值做比较,如果发现A发生了变化就把A返回给浏览器(200),不发生返回304
相同点:
- 如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据 不同点:
- 强缓存状态码200,协商缓存是304
- 强缓存不发请求到服务器,协商缓存会发请求到服务器
- 强缓存不发请求到服务器,所以有时候服务器资源更新了浏览器还不知道,造成服务器的资源更新了,浏览器还是老样子
- 但是协商缓存会发请求到服务器,所以资源是否更新,服务器肯定知道