在客户端访问网页的过程中,如果我们每次请求资源都去访问服务器,这样会增加服务器的负担,增加带宽压力和网页访问速度,利用缓存可以有效的解决这个问题。但是如果资源更改导致客户端更新不及时或者之前的版本有bug,缓存又会造成严重的后果。因此,为了避免设置缓存错误,掌握缓存的原理对于更加合理的配置缓存是非常重要。
强缓存和协商缓存
强缓存
什么是强缓存
- 强缓存:服务器端在
Response Headers
中设置的属性cache-control
和expires
进行缓存配置 - 当使用强缓存时,客户端获取资源并不会向服务器发起请求,而是直接在本地缓存获取,除非强缓存失效或刷新页面。
强缓存的设置
cache-control: max-age=xxxx,public
:
1.客户端和代理服务器都可以缓存该资源;
2.客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存
3.返回状态码:Statu code:200
4.如果用户做了刷新操作,就向服务器发起http请求
cache-control: max-age=xxxx,private
:
1.只有客户端可以缓存该资源;代理服务器不缓存
2.客户端在xxx秒内直接读取缓存
3.返回状态码:Status code:200
cache-control: max-age=xxxx,immutable
:
1.客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,即使用户做了刷新操作,也不向服务器发起http请求
2.返回状态码:Status code:200
cache-control: no-cache
:
1.跳过设置强缓存,但是不妨碍设置协商缓存;
2.一般如果你做了强缓存,只有在强缓存失效了才走协商缓存的
3.设置了no-cache就不会走强缓存了,每次请求都回询问服务端。
cache-control: no-store
:
1.不缓存,客户端、服务器都不缓存,也就没有所谓的强缓存、协商缓存。
强缓存的管理
ctrl+f5
强制刷新页面,解决页面直接引用的资源更新的问题- 使用浏览器的无痕模式开发
- chrome浏览器:f12在network中禁用缓存
- 在开发阶段,给资源加上一个动态的参数
- 如果缓存问题出现在ajax请求中,最有效的解决办法就是ajax的请求地址追加随机数
- 动态设置iframe的src时,有可能也会因为缓存问题,导致看不到最新的效果,这时候在要设置的src后面添加随机数也能解决问题
协商缓存
什么是协商缓存
- 协商缓存:客户端每次获取缓存都需要客户端和服务器进行交互。
- 客户端访问资源的过程中,当
Cache-Control
的值为no-cache
或max-age
过期,则不直接使用强缓存,而进行协商缓存。首先从本地缓存中获取etag
和last-modified
标识的值,之后发送含有if-none-matched (etag)
和if-modified-since (if-modified-since)
的标识的请求,服务器根据这两个值鉴权,判断资源是否被修改,如果资源没有被,返回304,浏览器读取本地缓存。如果资源有更改,返回200,返回最新的资源,并将此资源在缓存中更新 etag
:一个资源有唯一的etag5值,在http/1.1中规定Last-modified
:资源最后修改时间,在http/1.0中规定。不一定准确,比如服务器的修改资源的时间在1s之内,或者资源添加一个值,删除一个值,修改时间会改变,但是资源实际上是没有改变的。
协商缓存
- response header中的etag、last-modified在客户端重新向服务端发起请求时,会在request header中换个key名:
// response header
etag: '5c20abbd-e2e8'
last-modified: Mon, 24 Dec 2018 09:49:49 GMT
// request header 变为
if-none-matched: '5c20abbd-e2e8'
if-modified-since: Mon, 24 Dec 2018 09:49:49 GMT
- 协商缓存的触发条件
1.Cache-Control 的值为 no-cache
2.Cache-Control:max-age 过期
F5
会跳过强缓存规则,直接走协商缓存;Ctrl+F5
,跳过所有缓存规则,和第一次请求一样,重新获取资源
总结
浏览器启发式缓存策略
- 没有提供任何浏览器缓存过期策略时,浏览器遵循启发式缓存过期策略:根据响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期。浏览器会根据 Date 和 Last-Modified 之间的时间差值缓存一段时间,这段时间内会直接使用本地缓存数据而不会再去请求服务器(强制请求除外),缓存过期后,会再次请求服务端。
浏览器缓存策略
-
频繁变动的资源
Cache-Control: no-cache
对于频繁变动的资源,首先需要使用Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。 -
不常变化的资源
Cache-Control: max-age=31536000
通常在处理这类资源时,给它们的 Cache-Control 配置一个很大的 max-age=31536000 (一年),这样浏览器之后请求相同的 URL 会命中强制缓存。而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效。