两种缓存缓存机制
协商缓存
协商缓存的意思是文件虽然已经被缓存了,但是否从缓存中读取需要和服务端进行协商,也就意味着协商缓存需要发送请求和服务端通信
强制缓存
也就是强制从缓存中读取,无须发送请求和服务端通信
缓存的实现
强制缓存
在HTTP1.0的时候使用响应头中expires字段控制缓存,表示过期时间,是一个绝对时间。因为是绝对时间,所以在某些情况下,服务器的时区和浏览器的时区不一致,就会导致缓存失效。
之后在HTTP1.1引入了Cache-Control控制缓存,常用取值如下:
- max-age:缓存最大时间,是一个相对时间,不会出现expires绝对时间所导致的问题,单位秒
- public: 表示客户端和代理服务器都会缓存
- private:只在客户端缓存
- no-cache:协商缓存标识符,文件会被保存但是需要和服务器协商
- no-store:不会被缓存
协商缓存
协商缓存利用last-modified/if-modified-since,etag/if-none-match两对响应请求头实现的。
由于last-modified的时间粒度是秒, 某些情况下有的文件在1秒内可能会被改动多次,所以在HTTP1.1中引入了etag,根据文件内容生成一个标识符,和if-none-match比较,更准确的判断文件是否被更改
- 浏览器第一次发送请求获取文件缓存下来,服务器响应头返回last-modified记录被改动时间
- 浏览器第二次发送请求时会带上if-modified-since请求头,值为last-modified返回的值(请求头if-none-match对额值为响应头etag的值),然后服务器拿到这个字段和自己内部设置的时间进行比对判断是否修改过,如果时间相同表示没有修改,返回304读取缓存文件
- etag/if-none-match优先级高于last-modified/if-modified-since,强缓存优先级高于协商缓存
状态码上的区别
200 OK(from memory cache / disk cache)
大部分网站的静态文件都采用200 OK (from dist cache)或200 OK(from memory cache)这种缓存方式,除非客户端清楚缓存或使用ctrl+f5强制刷新页面,这两种都是强缓存。
- from memory cache:数据缓存在内存中,当杀掉进程(关闭浏览器),数据消失
- from dist cache: 数据缓存在磁盘中,杀掉进程,数据仍然存在,可以通过Ajax请求参数cache: false 禁止
读取流程一般就是:访问某个资源 —> 200 —> 退出浏览器再次进入—> 200 from disk cache —> 刷新 —> 200 from memory cache
304
协商缓存状态码,需要请求一次服务器,服务器认为没有内容更新时,则会返回304
浏览器加载过程
- 浏览器第一次加载时,服务器返回200,浏览器从服务器下载资源文件并缓存。
- 一次加载资源时,由于强制缓存优先级较高,先比较当前时间与上一次返回200的时间差,如果没有超过cache-control设置max-age,则没有过期,命中强缓存,直接从本地读取资源。如果不支持HTTP1.1,则使用expires头判断是否过期。
- 如果资源已过期,则表示没有命中强缓存,则开始协商缓存,向服务器发送带有If-None-Match和If-Modified-Since的请求
- 服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则表示没有修改,命中协商缓存,返回304。如果不一致则有改动,直接返回新的资源文件并携带新的Etag,返回200。
- 如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做对比,一致则命中协商缓存,返回304,不一致则返回新的last-Modified和文件并返回200
- cache-control优先级比expires高,同时存在只有cache-control生效