http里面cache-control了解吗?有什么作用?
Cache-Control 特性:
可缓存性(哪些地方可以执行缓存):
public(这个HTTP请求返回的内容所经过的任何路径当中,包括代理服务器以及发送请求的客户端浏览器,都可以进行对这个返回内容的缓存的操作)
private(只有发起请求的浏览器才可以进行缓存)
no-cache (我们可以在本地进行缓存,在proxy服务器进行缓存。每次发送请求时都要去服务器验证一下,如果服务器返回的请求告诉我们可以使用本地的缓存,我们才可以真正的使用本地的这部分缓存)
到期
max-age=时间(s)
s-maxage=时间(s)代替max-age,只有在代理服务器端才会生效
max-stale=时间(s) 在max-age过期之后,如果返回的资源里面有max-stale的设置,即便缓存已经过期了,只要在这个时间内,还可以使用过期的缓存。这个头在发起端设置才有用。
重新验证(很少用)
must-revalidate 在设置了max-age,已经过期了,我们必须去源服务端发送请求,重新获取数据来验证这个内容是否真的过期了,而不能直接使用本地的缓存。
proxy-revalidate 用在缓存服务器中
其他
no-store 区分no-cache (任何一个节点都不可以进行缓存,永远都要去拿新数据)
no-transform 主要用在proxy服务器那边,告诉代理服务器不要改动我们的内容。有时候返回的文件太大了,proxy服务器会做些压缩、格式的转换等
这些头只是限制性的,没有强制的约束力,可以不按照这个规范去做
Cache-Control设置了以后的效果
浏览器如何从本地读取缓存
页面中我们来缓存下script.js文件
加载了html之后,就会请求script.js
然后我们在script请求里面设置一下cache
重启下服务器
cache-control的作用:可以让请求从缓存里面去读取
如果我们把max-age设置的时间稍微长一点,再修改内容。
浏览器中刷新几次,从缓存中读取script文件,我们再修改一下内容
在300s之后,缓存过期后,才会加载新的内容,URL没有变,就还会从member cache里面去读。
Cache-Control是一个客户端缓存,如果我们设置了cache-control 就直接在客户端缓存了。根本不经过服务端的验证。在服务端更新了文件之后,客户端并不知道服务端已经更新了,还是从缓存中去读,就导致了静态资源更新后,没有及时更新到客户端。
我们希望浏览器缓存一些静态文件,又不希望服务端内容更新了以后客户端还是请求的缓存的旧的资源,我们想要更新一个应用的时候,客户端根本就触及不到,浏览器中我们一般设置为比较长的时间,常见的解决方案:
在做js,有个构建流程的时候,我们会在打包完成的js文件名上去根据内容的hash结果加上一串hash码。哈希码是根据打包的js文件以及其他静态资源的文件的内容进行的哈希计算,如果里面的内容不变,那么哈希码不变,反应到web页面上,就是URL没有变,那么我们就可以使用静态资源缓存。否则,嵌入在URL里面的路径就会有变化,发起的请求就是一个新的静态资源的请求。这样就能达到更新缓存的目的。
资源验证
如果我们给我们的cache-control设置了no-cache以后,每次浏览器发起设置了cache-control资源请求的时候,都会到服务器端进行资源的验证,验证完了以后,如果确定这个资源可以使用缓存,才会读取本地的缓存。
1、浏览器创建一个请求,请求首先到达的地方是本地缓存,如果已经找到了,就直接返回浏览器,浏览器显示页面,不需要经过任何网络的传输。
2、如果没有命中,就往互联网上发送,有可能会经过一个代理缓存的代理服务,代理服务里面也会查找相关缓存的设置。
3、如果代理服务器也没有命中,就会向源服务器请求。
数据进行验证
验证头
last-Modified : 上次修改时间 主要配合If-Modified-Since 或者 If-Unmodofied-Since使用。
如果我们请求一个资源,这个资源上面返回的header里面有last-Modified 这个头,指定了一个时间,这个时间在下次浏览器发起请求的时候,就会带上last-Modified传过来的值。通过If-Modified-Since 在请求里面就会把这个值带到服务器上。服务器就可以通过If-Modified-Since带来的值,对比资源存在的地方,对比它上次修改的时间,如果发现两个时间是一样的,代表这个资源还没有被修改过。服务器就可以告诉浏览器,可以直接使用缓存的资源。
对比上次修改时间以验证资源是否需要更新
Etag (更加严格的验证):数据签名(我们的资源对内容会产生唯一的签名,如果资源修改,签名就会变成新的) ,最典型的就是对资源的内容进行一个哈希计算。用这个签名来标记这个资源,下次浏览器发起请求的时候就会带上if-match或if-non-match这个头。这个值就是服务端返回的Etag的值。
配合if-match或if-none-match使用
对比资源的签名判断是否使用缓存(服务器的签名和浏览器传来的签名)
回到代码
刷新,再次发送请求,资源没有从缓存里面去取。
再看下响应头
在我们设置了这个头之后。浏览器下次就会把对应的缓存的头带上。
但是在response里面是有内容的
我们的内容实际上没有做任何的更改,这时候我们希望服务器不需要返回实际的内容,只需要让服务器告诉浏览器去读缓存。这时候需要在服务器做一个判断。
这时候在浏览器,
在response里面是有内容的,只是是之前的内容。
在Chrome里面,有个disable cache,如果勾上,则没有任何关于缓存的头和信息。
如果我们把设置的头里面的no-cache给去掉,刷新两次页面,则直接会是200 请求成功,并且from memory cache。
如果我们把no-cache换成no-store(根本没有任何缓存)
会忽略任何和缓存有关的信息。
直接认为是一个全新的请求。