强缓存
强缓存的实现
- 浏览器请求一个资源文件,服务端在response header中对该文件做缓存配置,缓存时间、缓存类型都由服务端控制。
- 之后每次用户正常打开这个页面,浏览器会判断缓存是否过期,没有过期就从缓存中读取数据并返回200状态。
cache-control
-
max-age=31536000
,表示资源最大有效时间的秒数,是一个相对值,不会因为用户修改本地时间而导致失效。 -
public/private
:public表示浏览器和代理服务器(nginx、CDN)都可以缓存;private表示仅浏览器端可以缓存。 -
immutable
:设置用户做了刷新操作(点击浏览器左上角的刷新按钮去刷新页面),也不向服务器发起http请求。 -
no-cache
:客户端缓存内容,但是是否使用缓存需要经过协商缓存来验证决定(即每次请求都会询问服务端)。 -
no-store
:浏览器端、服务器端都不缓存,即不使用强制缓存也不使用协商缓存。
协商缓存
- 强制缓存内容失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
- 协商缓存其实受强缓存的影响,强缓存过期了且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消耗更大一些。