强缓存
强缓存的实现
- 浏览器请求一个资源文件,服务端在response header中对该文件做缓存配置,缓存时间、缓存类型都由服务端控制。
- 之后每次用户正常打开这个页面,浏览器会判断缓存是否过期,没有过期就从缓存中读取数据,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。
cache-control
max-age=31536000
,表示资源最大有效时间的秒数,是一个相对值,不会因为用户修改本地时间而导致失效。public/private
:public表示浏览器和代理服务器(nginx、CDN)都可以缓存;private表示仅浏览器端可以缓存。immutable
:设置用户做了刷新操作(点击浏览器左上角的刷新按钮去刷新页面),也不向服务器发起http请求。no-cache
:客户端缓存内容,但是是否使用缓存需要经过协商缓存来验证决定(即每次请求都会询问服务端)。no-store
:浏览器端、服务器端都不缓存,即不使用强制缓存也不使用协商缓存。
Expires
- 它的值是一个绝对的时间,这个时间代表资源的失效时间,就是说在这个时间之前缓存始终有效,始终会读取缓存中的数据。
- Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,造成服务器时间与客户端时间有偏差时,可能会造成缓存失效。
Expires和Cache-Control两者对比
- Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires;
- 在某些不支持HTTP1.1的环境下,Expires就会发挥用处。所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法。
协商缓存
- 强制缓存内容失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
- 协商缓存其实受强缓存的影响,强缓存过期了且Cache-Control不为no-store时是否缓存才由协商缓存决定。
- 协商缓存是通过两对值来设置的: Last-Modified/If-Modified-Since 和 ETag/If-None-Match。
协商缓存的步骤
- 请求资源时,把用户本地该资源的 etag 同时带到服务端,服务端和最新资源做对比。
- 如果资源没更改,返回304,浏览器读取本地缓存。
- 如果资源有更改,返回200,返回最新的资源。
ETag与Last-Modified
- 浏览器第一次发送一个请求得到ETag/Last-Modified的值,在下一次请求request header中带上If-none-match/If-Modified-Since,根据浏览器端发送的值和服务器端的值进行比较,如果一致代表资源没有改变,服务器返回的正文为空的响应(304),让浏览器从缓存中读取资源,从而减少请求消耗。
- Last-Modified 和 ETag同样可以同时配置,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
Last-Modified的缺点
- Last-Modified保存的是绝对时间,并且是精确到秒,所以如果资源在1秒内修改了多次的话,那就无法识别;
- 对于文件只改变了修改时间,内容不变,这时候也会使缓存失效,其实这个时候我们是不希望客户端重新请求的;
- 某些服务器不能精确的得到文件的最后修改时间
ETag的缺点
- ETag的出现主要是解决了Last-Modified难以解决的问题,但是它也并非完美的,ETag每次服务端生成都需要进行读写操作(因为要生成hash),而Last-Modified只需要读取操作,ETag消耗更大一些。