😎 对浏览器缓存机制的理解
浏览器缓存的全过程:
- 浏览器第一次加载资源,服务器返回
200 ,浏览器从服务器下载资源文件,并缓存资源文件与response header ,以供下次加载的时候对比使用 - 下一次加载的时候,由于强制缓存优先级比较高,先比较当前时间与上一次返回
200 时的时间差,如果没有cache-control 设置的max-age ,则没有过期,命中强缓存,直接从本地读取资源。如果浏览器不支持HTPP1.1 ,则使用expires 头判断是否过期 - 如果资源已过期,则表明强制缓存没有命中,则开始协商缓存,向服务器发送带有
If-None-Match 和If-Modified-since 的请求 - 服务器收到请求后,优先根据
Etag 的值判断被请求的文件又没有做修改,Etag 值一致则没有修改,命中协商缓存,返回304 ;如果不一致则有改动,直接返回新的资源文件带上新的Etag 值并返回200 ; - 如果服务器收到的请求没有
Etag 值,则将If-Modified-Since 和被请求文件的最后修改时间做出比对,一致则命中协商缓存,返回304 ;不一致则返回新的last-modified 和文件并返回200 很多网站的资源后面都加了版本号,这样做的目的是:每次升级了JS或者CSS文件后,为了防止浏览器进行缓存,强制改变版本号,客户端浏览器就会重新下载新的JS或CSS文件,以保证用户能及时获得网站的最新更新。
🤔 浏览器资源缓存位置有哪些
资源缓存的位置?共有 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 Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使?,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源?旦被硬盘缓存下来,就不会再次去请求数据。
😇 协商缓存和强缓存的区别
1. 强缓存
使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必再向服务器发送请求。
强缓存策略可以通过两种方式设置,分别是http头信息中的Expires属性 和Cache-Control 属性
(1) 服务器通过在响应头中添加Expires属性,来指定资源的过期时间。在过期时间以内,该资源可以被缓存使用,不必再向服务器发送请求。这个时间是一个绝对时间,它是服务器的时间,因此可能存在这样的问题,就是客户端的时间和服务端的时间不一致,或者用户可以对客户端的时间进行修改的情况,这样就可能会影响缓存命中的结果。
(2) Expires是http1.0中的方式,因为它的一些缺点,在HTTP1.1中提出一个新的头部属性就是Cache-Control属性,它提供了对资源的缓存的更精确的控制。
Cache- Control 可设置的字段
public :设置了该字段值的资源表示可以被任何对象缓存。这个字段不常用,一般还是用max-age=来精确控制private :设置了该字段的资源只能被用户浏览器缓存,不允许任何代理服务器缓存。在实际开发中,对于一些含用用户信息的HTML,通常都要设置这个字段值,避免代理服务器(CDN)缓存no-cache :设置了该字段需要先和服务端确认返回的资源是否发生了变化,如果资源未发生变化,则直接使用缓存好的资源no-store :设置了该字段表示禁止任何缓存,每次都会向服务端发起新的请求,拉取最新的资源max-age= :设置缓存的最大有效期,单位为秒s-maxage= :优先级高于max-age,仅适用于共享缓存(CDN),优先级高于max-age或者Expires头max-stale[=] :设置了该字段表示客户端愿意接收已经过期的资源,但是不能超过给定的时间限制。
一般只需要设置其中一种方式就可以实现强缓存策略,当两种方式一起使用时,Cache-Control 的优先级高于Expires
no-cache和no-store很容易混淆:
- no-cache 是指先要和服务器确认是否有资源更新,再进行判断。也就是说没有强缓存,但是会有协商缓存
- no-store是指不使用任何缓存,每次请求都直接从服务器获取资源
2. 协商缓存
如果命中强制缓存,我们就无需发起新的请求,直接使用缓存内容,如果没有命中强制缓存,如果设置了协商缓存,这个时候协商缓存就会发挥作用了。
上面说到命中协商缓存有两个条件:
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生更改,则返回一个304状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。
协商缓存也可以通过两种方式来设置,分别是http头信息中Etag 和Last-Modified 属性
(1) 服务器通过在响应头中添加Last-Modified属性来指出资源最后一次修改的时间,当浏览器下一次发送请求的时候,会在请求头中添加一个If-Modified-Since的属性,属性值为上一次资源返回时的Last-Modified的值。当请求发送到服务器后服务器会通过这个属性来和资源的最后一次的修改时间来进行比较,一次判断资源是否做了修改。如果资源没有修改,那么返回304状态,让客户端使用本的的缓存。如果资已经被修改了,则返回修改后的资源。
使用这种方法有一个缺点 ,就是
Last-Modified 标注的最后修改时间只能精确到秒级,如果某些文件在1秒中以内,被修改多次的话,那么文件已经改变了,但是Last-Modified 却没有改变,这样会造成缓存命中的不准确。
(2) 因为Last-Modified 的这种可能发生的不准确性,http中提供了另外一种方式,那就是Etag 属性。服务器在返回资源的时候,头部添加了Etag 属性,这个属性时资源生成的唯一标识符,当资源发生改变的时候,这个值也会发生改变。在下一次资源请求的时候,浏览器会在请求头中添加一个If-None-Match 属性,这个属性的值就是上次返回的资源的Etag 值。服务器接收到请求后会根据这个值来和资源当前的Etag 值来进行比较,以此判断资源是否发生改变,是否需要返回资源。通过这种方式,比Last-Modified 的方式更加精确
当 Last-Modified 和 Etag 属性同时出现的时候,Etag 的优先级更?。使?协商缓存的时候,服务器 需要考虑负载平衡的问题,因此多个服务器上资源的 Last-Modified 应该保持?致,因为每个服务器上 Etag 的值都不?样,因此在考虑负载平衡时,最好不要设置 Etag 属性。
总结
两种缓存策略在缓存命中时都会直接使用本地的缓存副本,区别只在于协商缓存会向服务器发送一次请求。它们缓存不命中时,都会向服务器发送请求来获取资源。在实际的缓存机制中,强缓存策略和协商缓存策略是一起合作使用的。浏览器首先会根据请求的信息判断,强缓存是否命中,如果命中则直接使用资源。如果不命中则根据头信息向服务器发起请求,使用协商缓存,如果协商缓存命中的话,则服务器不返回资源,浏览器直接使用本地资源的副本,如果协商缓存不命中,则服务器返回最新的资源给浏览器。
😋 为什么需要浏览器缓存
对于浏览器的缓存,主要针对的是前端的静态资源,最好的效果就是,在发起请求之后,拉取相应的静态资源,并保存在本地。如果服务器的静态资源没有更新,那么在下次请求的时候,就直接从本地读取即可,如果服务器的静态资源已经更新,那么我们再次请求的时候,就到服务器拉取新的资源,并保存在本地。这样就??的减少了请求的次数,提?了?站的性能。这就要?到浏览器的缓存策略了。
所谓的浏览器缓存指的是浏览器将?户请求过的静态资源,存储到电脑本地磁盘中,当浏览器再次访问时,就可以直接从本地加载,不需要再去服务端请求了。
使用浏览器缓存有以下优点:
- 减少了服务器的负担,提高了网站性能
- 加快了客户端网页的加载速度
- 减少了多余的网络数据传输
🧐 点击刷新按钮或者按F5、Ctrl+F5(强制刷新)、地址栏回车有什么区别
- 点击刷新按钮或者按F5:浏览器直接对本地缓存文件过期、但是会带上
If-Modified-Since 、If-None-Match 、这就意味着服务器会对文件检查新鲜度,返回结果可能是304,也可能是200 - 按Ctrl+F5 (强制刷新):浏览器不仅会对本地文件过期,而且不会带上
If-Modified-Since 、If-None-Match ,相当于之前从来没有请求过,返回结果是200 - 地址栏回车:浏览器发起请求,按照正常流程,本地检查是否过期,然后服务器检查新鲜度,返回内容
|