背景:为了提高用户体验,加快加载速度,减少服务器负担,减少不必要的数据传输,节省带宽,可以借助浏览器缓存来实现。
浏览器缓存分为:强缓存和协商缓存
一、强缓存
强缓存:不会向服务器发起请求,会看缓存中是否有未过期的缓存,当浏览器去请求某个资源时,通过服务器设置响应头字段cache-control或expires来设置缓存的时间、缓存类型。当缓存中有未过期的缓存,读取缓存并返回statecode200状态。
1.1 cache-control(HTTP1.1)
常用值设置:max-age(缓存时间)、public(客户端和代理服务器都可以缓存该资源)/private(仅客户端可以缓存该资源)、immutable(在有效期内直接读取缓存)、no-cache(跳过强缓存,直接进入协商缓存)/no-store(跳过强缓存和协商缓存)
设置例子如下:
1.cache-control: max-age=xxxx,public
客户端和代理服务器都可以缓存该资源。在缓存有效期内,直接读取缓存,statecode为200。当用户刷新页面时,还是会像服务器发起http请求。
2.cache-control: max-age=xxxx,private
仅客户端可以缓存该资源。在缓存有效期内,直接读取缓存,statecode为200。当用户刷新页面时,还是会像服务器发起http请求。
3.cache-control: max-age=xxxx,immutable
在缓存有效期内,直接读取缓存,statecode为200。当用户刷新页面时,不会向服务器发起请求,而是直接读取缓存。
4.cache-control: no-cache
跳过强缓存,直接进入协商缓存。(原为强缓存失效之后,才会进行协商缓存)
5.cache-control: no-store
强缓存和协商缓存都失效,直接向服务器请求资源。
1.2 expires(HTTP1.0)
可以通过expires指定资源的过期时间。是一个绝对时间,由服务器决定。
1.3 cache-control和expires优先级
当cache-control和expires发生冲突时,cache-control的优先级更高。
原因有两点,如下:
1.expires通过具体的时间戳定义缓存的过期时间,由服务器决定。但是客户端时间可以修改,当客户端和服务端时间不一致的时候会出现问题。
2.当cache-control中设置了“max-age”这类时,expires头会被忽略。
二、协商缓存
当强缓存失效或者被跳过时,进入协商缓存,协商缓存需要和服务器进行交互。在客户端第一次向服务器发起请求时,通过服务器设置响应头etag(HTTP1.1)和last-modified(HTTP1.0)来指明资源标识和文件修改的时间。当浏览器再向服务器发起请求时,请求头会携带If-None-Match(对应etag)和If-Modified-Since(对应last-modified)来匹配资源和记录上次资源修改的时间(即上个响应头中的last-modified)。当匹配成功时,statecode为304,不会返回资源,客户端读取缓存。当匹配失败时,statecode为200,返回资源。
注意:为什么HTTP1.1中要引入etag/If-None-Match?
1.last-modified/If-Modified-Since精确到秒,秒以下的变化无法判断。
2.当资源修改时,内容不做更改时,无需重新请求资源。
3.某些服务器不能精确的得到文件的最后修改时间。
当etag/If-None-Match和last-modified/If-Modified-Since一起使用时,etag/If-None-Match的优先级更高。
三、缓存的顺序
首先会命中强缓存,若强缓存未击中或跳过才会去进入协商缓存。
三、强缓存和协商缓存的相同点和不同点
相同点:击中缓存时,都是在客户端读取缓存。
不同点:强缓存不会强制向服务器发起请求(除了有些情况,用户强制刷新页面),协商缓存需要跟服务器进行交互,一定会向服务器发起请求。