目录
1.对浏览器的缓存机制的理解
浏览器缓存的全过程:
- 浏览器第一次加载资源,服务器返回200,浏览器从服务器下载资源文件,并缓存
资源文件
与response header
,以供下次加载时对比使用; - 下一次加载资源时,由于
强制缓存优先级较高
,先比较当前时间与上一次返回200时的时间差,如果没有超过cahe-control
设置的max-age
,则没有过期,并命中强缓存
,直接从本地读取资源。 - 如果资源过期了,则表明强缓存没有被命中,则开始
协商缓存
,向服务器发送带有If-None-Match
和If-Modified-Since
的请求。 - 服务器收到请求后,优先根据
Etag(Entity tag)
的值判断请求的文件有没有做修改,Etag
值一致则没有修改,命中协商缓存,返回304
;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200
。 - 如果服务器收到的请求没有
Etag
值,则将If-Modified-Since
和被请求文件的最后修改时间
做对比,一致则命中协商缓存,返回304
;不一致则返回新的last-modified和文件并返回200
。
2.浏览器资源缓存的位置有哪些?
浏览器缓存的位置一共有3种,按照优先级从高到低分别是:
Service Worker
:Service Worker运行在JavaScript主线程之外,虽然由于脱离了浏览器窗体无法直接访问DOM,但是它可以完成离线缓存,消息推送,网络代理等功能。它可以让我们自由控制缓存哪些文件,如何匹配缓存,如何读取缓存,并且缓存是持续性的。当Service Worker没有命中缓存的时候,需要去调用fetch函数获取数据。也就是说,如果没有在service worker命中缓存,会根据缓存查找优先级去查找数据。但是不管是从Memory Cache中还是从网络请求中获取的数据,浏览器都会显示是从Service Worker中获取的内容。Memory Cache
: Memory Cache就是内存缓存,它的效率最高,但是内存缓存虽然读取高效,可是缓存持续性会很短,会随着进程的释放而释放。一旦我们关闭Tab页面,内存中的缓存也就被释放了。Disk Cache
: Disk Cache也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之Memory Cache胜在容量和存储实效上。在所有浏览器缓存中,Disk Cache覆盖面基本是最大的。它会根据HTTP Header中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。
3.协商缓存和强缓存的区别
1)强缓存
强缓存的强就是强制
的意思。当浏览器去请求某个文件的时候,服务端
就在response header
里面对文件做了缓存配置
。缓存时间
,缓存类型
都由服务端
控制。
具体表现如下图所示:
不同的cache-control的含义:
cache-contro: max-age=1000, public
表示客户端和代理服务器都可以缓存该资源
客户端在1000秒的有效时间内,如果有请求该资源的需求的话就直接读取缓存,status code:200,如果用户做了刷新操作,就向服务器发起http请求。cache-control: max-age=1000,private
只让客户端可以缓存该资源;代理服务器不缓存
客户端在1000秒内直接读取缓存,status code:200cache-control: max-age=1000,immutable
客户端在1000秒的有效时间内,如果有请求该资源的需要的话就直接读取缓存,status code:200,即使用户做了刷新操作,也不向服务器发起http请求。cache-control: no-cache
跳过强缓存设置,但是不妨碍设置协商缓存;一般如果你做了强缓存,只有在强缓存实效了才走协商缓存的,设置了no-cache就不会走强缓存了,每次请求都会询问服务器。
5.cache-control:no-store
不缓存,这个会让客户端,服务器都不缓存,也就没有所谓的强缓存,协商缓存了。
2)协商缓存
强缓存就是给资源设置一个过期时间,客户端每次请求资源都会看是否过期;只有在过期才会去询问服务器。所以,强缓存就是为了给客户端自给自足用的。而当某天,客户端请求该资源时,发现其过期了,这就会去请求服务器了,而这时候去请求服务器的过程就可以设置协商缓存。这时候,协商缓存就是需要客户端和服务端进行交互。
在response header
里面设置协商缓存:
etag: '5c20abbd-e2e8'
last-modified: Mon, 24 Dec 2018 09:49:49 GMT
etag
:每个文件有一个,改动文件了就变了,这就是个文件hash,每个文件唯一。
last-modified
:文件修改时间,精确到秒
也就是说每次请求返回来的response header
中都带有etag
和last-modified
,在下次请求时,request header
再把etag
和last-modified
带上,服务器再对这两个标识进行对比,然后判断资源是否过期。
如果资源过期了就返回200状态码
,且返回新的资源和更新对应的response header
的标识etag
和last-modified
。
如果资源没有过期,那就不变etag
和last-modified
,这时候对客户端来说,每次请求都要进行协商缓存了,即返回304状态码
,客户端用缓存的老资源。
注意点:response header
中的etag
和last-modified
在客户端重新向服务器端发起请求时,会在request header
中换一个键值名
// 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
4.为什么需要浏览器缓存?
所谓的浏览器缓存指的是浏览器将用户请求过的静态资源
,存储到电脑本地磁盘中
,当浏览器再次访问时,就可以直接从本地加载,不需要再去服务端请求了。
对于浏览器的缓存,主要针对的是前端的静态资源
,最好的效果是,在发起请求之后,拉去相应的静态资源,并保存在本地。如果服务器的静态资源没有更新,那么下次请求的时候,就直接从本地读取即可,如果服务器的静态资源已经更新,那么我们再次请求的时候,就到服务器拉取新的资源,并保留在本地。这样就大大的减少了请求的次数,提高了网站的性能。这就要用到浏览器的缓存策略了。
5.点击浏览器刷新按钮或者按F5,按Ctrl+F5(强制刷新),地址栏回车有什么区别?
- 点击刷新按钮或者按F5:浏览器直接视本地的缓存文件过期,但是
request header
会带上Etag
和If-Modified-Since
,这时候服务器就会判断文件是否被修改过,所以返回的状态码可能是304
,也有可能是200
。 - 用户按Ctrl+F5(强制刷新):浏览器不仅会视本地的缓存文件过期,在
request header
中也不会携带Etag
和If-Modified-Since
,返回的状态码为200
。 - 地址栏回车:浏览器发起请求,按照正常流程,本地检查是否过期,然后服务器检查文件是否被修改,最后返回内容。