写在文首
这两篇文章讲的非常透彻,大家都可以去学习一下
下文有部分搬运
浏览器缓存的几个优点
- 减少重复数据请求,避免通过网络再次加载资源,节省流量
- 降低服务器压力,提升网站性能
- 加快客户端加载网页的速度,提升用户体验
缓存基本原理
- 浏览器在加载资源时,根据请求头的expires和cache-control来判断是否命中强缓存,是则直接从缓存中读取资源,不发送请求到服务器
- 如果没有命中强缓存,浏览器会发送请求至服务器,通过last-modified和etag验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取数据
- 如果前面两者都没有命中,直接从服务器加载资源
强缓存与协商缓存的异同
- 相同点:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据
- 不同点:强缓存不发请求到服务器,协商缓存会发请求到服务器
请求流程
强缓存
强缓存根据返回头中的expires和cache-control两个字段控制,都表示资源的缓存有效时间。
Expires是 http 1.0 的规范,值是一个GMT 格式的时间点字符串,比如Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间点代表资源失效的时间,如果当前的时间戳在这个时间之前,则判定命中缓存。有一个缺点是,失效时间是一个绝对时间,如果服务器时间与客户端时间偏差较大时,就会导致缓存混乱。而服务器的时间跟用户的实际时间是不一样是很正常的,所以Expires在实际使用中会带来一些麻烦。Cache-Control这个字段是 http 1.1 的规范,一般常用该字段的 max-age 值来进行判断,它是一个相对时间,比如.Cache-Control:max-age=3600代表资源的有效期是 3600 秒。并且返回头中的 Date 表示消息发送的时间,表示当前资源在Date ~ Date +3600s这段时间里都是有效的。不过我在实际使用中常常遇到设置了 max-age 之后,在 max-age 时间内重新访问资源却会返回304 not modified,这是由于服务器的时间与本地的时间不同造成的。当然 Cache-Control 还有其他几个值可以设置, 不过相对来说都很少用了- 如果expires和cache-control同时存在,cache-control的优先级更高
协商缓存
协商缓存最终由服务器来决定是否命中 ,利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】两对header进行控制。
Last-Modified标记了文件最后的修改时间,在请求头中会带有If-Modified-Since字段,通过比较这两个字段来判断文件有没有发生过变化。如果没有变化则返回304 Not Modified,Etag是服务器中每一个资源生成的唯一标识符,只要资源有变化这个值就会改变。通过比较请求头的If-None-Match字段判断文件是否有变化。
Etag优先级高于Last-Modified
Last-modified的值只精确到秒级,若一个文件已毫秒级的速度进行更新,则会产生误判- 文件若每隔一段时间都重复生成,但是内容相同,只有最后修改时间进行了变化,这种情况我不希望客户端认为这个文件被修改了
优先级
cache-control > expires > etag > last-modified