浏览器缓存——强缓存和协商缓存
为了减轻服务器的压力,http提供了一个叫做缓存的解决方案。当数据没有发生变化时,浏览器每次都从缓存中读取数据,但是这样有个问题就是浏览器怎么知道服务器何时更新了资源。于是我们把缓存添加了一个有效时间,只要缓存过期,浏览器就会重新向服务端发起请求,这个缓存有效的时间主要由服务端设置。
强缓存(本地缓存)
概念
不需要跟服务器进行通信,直接使用本地缓存的资源
相关的header字段
**
expires
**: 缓存过期时间, 一个未来时间,代表资源何时无效缺点: 这种方法有个弊端就是当
服务器时间和浏览器端的时间不同步
时,就会导致一些错误,于是出现了下面的改进方法:**
cache-control(http1.1)
**:这种方法采用相对时间的方式,有效时间从浏览器端收到响应结果开始生效
max-age
:代表在这个请求正确返回的时间的一段时间内再次加载资源,就会命中强缓存。no-cache
:不使用本地缓存,向浏览器发送新鲜度校验请求no-store
:禁止缓存浏览器数据,也禁止保存至临时文件中,每次都重新请求public
:任何情况下都缓存(即使是HTTP认证的资源)private
:只能被终端用户的浏览器缓存,不允许CDN等中间层缓存服务器对其进行缓存
协商缓存
概念
首先,将所缓存资源的信息发送给服务器,
其次,让服务器判断资源是否已经更新了
- 若已更新,则返回更新后的资源;
- 若没有更新,则返回304状态,告诉浏览器可直接使用本地缓存的资源
整个过程至少与服务器通信一次
相关header字段
响应头: Last-Modified
请求头:If-Modified-Since
(资源修改时间)
请求过程:
- 浏览器第一次发送请求,服务器在响应头上加上
Last-Modified
字段表示资源的最后修改时间. - 浏览器第二次以及之后请求,都会在请求头上加上
If-Modified-Since
字段,值为服务器返回的Last-Modified
- 服务器根据请求传过来的值判断资源是否有变化,没有则返回
304
, 有变化就正常返回资源内容,更新 Last-Modified 的值
- 如果服务端返回
304
状态码,则从缓存加载资源,否则直接使用服务器返回的数据
缺点:但是这种方法还有个缺陷就是返回的时间的单位是秒级
的,会遗漏掉毫秒级
的修改,这时就出现了另一个策略
响应头:Etag
请求头:If-None-Match
一个标识符字符串,表示文件唯一标识,只要文件内容改动,ETag就会重新计算。缓存流程和 Last-Modified
一样。
浏览器缓存过程(强缓存转协商缓存的过程)
- 浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并
把文件、文件的返回时间、response header一并缓存
; - 下一次加载资源时,查看
cache-control
的设置- 如果值是
no-cache
,则表示不缓存,则直接去请求数据 - 如果值是
max-age
,则比较当前时间和上一次返回200响应成功时的时间差
是否大于max-age,若小于max-age,则表示没有过期,此时命中强缓存,不发送请求直接从本地缓存读取该文件;如果时间差大于max-age,则表示资源过期了,则向服务器发送请求,并且header中携带有If-None-Match、If-Modified-Since、Etag值等
- 如果值是
- 如果服务器收到的请求头中,有Etag值,
优先根据Etag的值
判断被请求的文件有没有做修改,
如果Etag值一致则没有修改,命中协商缓存,返回304,则读取缓存资源;
如果Etag值不一致则有改动,则直接返回新的资源,并带上新的Etag值; - 如果服务器收到的请求头中,没有Etag值,则将
If-Modified-Since
和被请求文件的最后修改时间
做比对,
如果一致则没有修改,命中协商缓存,返回304;
如果不一致则有修改,则返回新的文件和并在响应头中携带last-modified
,下次请求时通过If-Modified-Since
携带上last-modified
的值;