文章目录
浏览器的缓存机制即是HTTP的缓存机制,因为其完全是由HTTP来控制的。
1.缓存的位置:
service worker:单独的一个线程,用来实现缓存功能;
memory cache:内存中的缓存;容量小,存储时间短;
disk cache:硬盘上的缓存,容量大,时效性长;(绝大部分的缓存都来自 Disk Cache,与HTTP的缓存策略有很大的关联)
2.缓存过程的分析:
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识。
如果找不到则向服务器发送请求,拿到请求结果后又会根据资源响应头决定是否将该结果和缓存标识存入浏览器缓存中。
3.浏览器的缓存策略:
浏览器缓存策略分为两种:强缓存和协商缓存。都是由服务器返回的响应报文中的头字段决定的。
3.1强缓存
强缓存:客户端再次请求资源时,不会向服务器发送请求,而是直接从缓存中读取资源
两种实现方式:
(1)Expires方法(设置过期时间)
Expires 是 HTTP/1 的产物,表示缓存资源到期的时间,如果系统的时间小于该时间,则不会发送请求。
由于系统的时间是可以修改的,所以修改了时间的话不一定会满足预期。
(2)Cache-Control方法(设置过期时间)
Cache-Control是HTTP/1.1新增的字段,主要用于控制网页缓存。
-
public指令: 响应内容会被客户端和代理服务器缓存
-
private指令:响应内容只能被客户端缓存
-
max-age指令:表示缓存的响应内容的有效期,即在xx秒后失效
-
s-maxage指令:表示缓存在代理服务器中的响应内容在xxx秒后失效,s-maxage的优先级比max-age高。
-
其他指令:
-
no-store指令: 表示服务器响应的内容不使用缓存
-
no-cache指令(该指令用于协商缓存):表示客户端在从缓存取数据之前,需要会先向服务器发送请求验证当前缓存内容是否有更新,如果有,服务器会返回新的响应报文。
-
(3)Expires和Cache-Control两者对比:
Expires 是http1.0的产物,Cache-Control是http1.1的产物。Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法。
两者同时存在的话,Cache-Control优先级高于Expires;
3.2协商缓存:
协商缓存:客户端再次请求资源时时,会向服务器发送请求验证当前资源的有效性
两种实现方法:
(1)Last-Modified(根据文件修改时间来决定是否从缓存取数据)
-
浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified字段,值是这个资源在服务器上的最后修改时间,浏览器接收后会缓存文件和header;
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
-
由于存在no-cache指令,所以浏览器会向服务器发送请求验证缓存的内容是否有更新,请求的报文中会添加一个if-Modified-Since字段,值就是之前缓存标识中的Last-Modified;
-
服务器收到这个请求时,会将 If-Modified-Since 中的值与服务器中这个资源的最后修改的时间进行对比。
-
如果没有变化,返回状态码为304的空的报文,然后客户端是直接从缓存读取数据;
-
如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是就返回状态码为200的新资源。
-
最后浏览器再将新的响应报文和对应的缓存标识缓存起来。
(2)Etag方法(根据文件内容是否修改来决定是否从缓存取数据)
-
Etag字段是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。
-
具体过程与Last-Modified类似,只是时间的比较变成了资源唯一标识符的比较。
-
服务器在第一次响应的报文中会添加一个Etag字段,存储的是当前资源文件的唯一标识。
-
浏览器在下一次发送请求时会在请求头中添加If-None-Match字段,取值就是之前的Etag值。
-
服务器在接收到请求后会将该字段的值与当前资源文件的ETag进行比较;
-
若相同,则表示资源没有更新,会返回状态码为304的空报文。表示浏览器从本地缓存中取数据。
-
若不同,则会返回状态码为200的新资源。
(3)Last-Modified与Etag两者比较
-
在精确度上,Etag要优于Last-Modified;采用Last-Modified方法时,如果服务器端在不可感知的时间里修改了文件,Last-Modified其实并没有体现出来修改,此时客户端获取到的仍是旧数据。
-
性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值
-
优先级上,服务器校验优先考虑Etag
4.浏览器的缓存机制:
-
强制缓存优先于协商缓存进行
-
若强制缓存(Expires和Cache-Control)生效则直接使用缓存,不再走协商缓存路线
-
若时间已过期则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)
- 协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效了,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;
- 生效则返回304,继续使用缓存。
5.实际场景中的缓存策略应用:
- 频繁变动的资源:将Cache-Control字段设置为no-cache,表示每次请求都要验证资源的有效性
- 不常变化的资源:Cache-Control: max-age=31536000,将过期时间设置为1年。其实实际上在发送请求的时候会在路径中添加hash来更改url,发起新的请求。
- 输入url,回车:按照整个缓存机制进行,先走强缓存,再走协商缓存。
- 浏览器点击刷新按钮或者按
F5
刷新:发送的请求头带有:Cache-Control:max-age=0,表示不走强制缓存这条路,可以走协商缓存向服务器发起数据请求。 ctrl
+F5
强制刷新:发送的请求头带有Cache-Control:no-cache ,表示不走缓存这条路。直接向服务器发送新的请求。- 浏览器的前进,后退,跳转是直接从缓存里取数据。