前言:在前天的面试中被问到了浏览器是如何实现缓存的,当时回答的乱七八糟,所以今天就总结一下关于浏览器缓存的知识,希望给自己加深印象,也能帮到更多有需要的人。
一. 资源为什么需要被浏览器缓存?
因为有些网站作为普通用户我们可能会每天都访问,或者在进入网站后,我们会多次访问同一个页面,如果每次都从服务器去加载资源的话,一直在做重复的事,对服务器来说会是一种浪费,对用户来说,每次请求资源都需要去等待服务器发送资源,毫无疑问增加了用户的等待时间,这对用户来说是非常不好的体验,主要针对这两方面的原因,对必要的资源进行缓存是非常必要的。
二. 浏览器如何实现缓存?
浏览器实现缓存是有HTTP Header决定的,主要包括:Cache-Control,Last-Modified/If-Modified-Since,Etag/If-None-Match,Expires
。
(1)Cache-Control的主要参数:
Cache-Control: private/public; Public:指示响应可被任何缓存区缓存。Private:指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。
Cache-Control: no-cache:不进行缓存 ;
Cache-Control: max-age=x:缓存的周期,以秒为单位 ;
Cache-Control: must-revalidate:如果页面是过期的则去服务器进行获取。
(2)Last-Modified/If-Modified-Since
Last-Modified:服务器发送来的资源的最后修改时间,在HTTP的Response Header中,用来标识资源的过期时间;
If-Modified-Since:客户端发送给浏览器的,在HTTP的Request
Header中,是服务器发来的Last-Modified的值,用来验证资源是否被修改;
(3)Etag/If-None-Match
Etag:服务器发来的,在HTTP的Response Header中,是资源在服务器的唯一标识;
If-None-Match:客户端发送给浏览器的,在HTTP的Request Header中,验证Etag是否改变,即资源是否被修改;
(4)Expires
所要缓存资源的过期时间,用来判断资源是否过期,是否需要向服务器发起请求;
上面主要是关于浏览器缓存有关的响应头信息和请求头信息中的一些字段的介绍,接下来看一下浏览器是如何利用这些字段来实现对缓存的处理的。
先看一张图,答案就会很明确了:
1 . 从图片可以看出对于用户不同的请求方法,浏览器对缓存有不同的处理:
1)按下Ctrl+F5:不管是否缓存,都会去请求新的资源;
2)按下F5或打开新的页面会强制使Cache-Control的max-age=0,所以直接判断ETag的值;
3)在导航栏输入地址,点击页面链接,以及回退和前进都会去按照标准的流程对缓存进行判断,最后返回页面;
2 . 浏览器对缓存处理的标准流程:
1)查看缓存是否过期,没有过期直接返回状态码200,使用浏览器缓存,返回页面。判断过期结合Expires和Cache-Control的max-age的值;
2)如果过期,则查看ETag的值是否被修改,没有修改则服务器返回状态码304,使用浏览器缓存,返回页面;
3)如果ETag被修改,询问服务器Last-Modified是否修改,即根据请求头里的If-Modified-Since和服务端进行比对,如果没有过期,服务器返回状态码304,使用浏览器缓存,返回页面;
4)如果Last-Modified改变,返回状态码200,并返回要请求的资源,返回页面;
注意:
在判断缓存是否过期时Cache-Control的max-age优先级高于Expires;
在判断过期的缓存是否可用的过程中ETag的优先级高于Last-Modified;