当前位置: 首页 > Web前端 > HTML

【困惑系列】第二问:都2022年了,你知道强制缓存和协商缓存吗?

时间:2023-03-28 17:45:51 HTML

大家好,我是毛小白,本文是关于前端混淆知识点的第二题,致力于打好基础,消除模糊知识点。本文重点:为什么需要缓存机制。强制缓存和协商缓存是针对静态文件资源的。它们之间有什么区别或联系?一些动态接口是如何缓存的?服务器如何设置缓存,浏览器如何使用缓存?我们都知道为什么需要缓存机制。对于用户来说,越早访问网站越好。对于服务器来说,响应速度越快越好,压力越小越好。有了缓存,这些问题就可以轻松解决了~。当浏览器第一次访问服务器时,服务器返回相应的资源,同时告诉浏览器保存该资源。下次你需要的时候,只要没过期,你自己用就可以了,不用再问我。你知道的,我很忙~第一次进入某个网站的时候,会比较慢,因为没有本地缓存??,所以需要打扰服务器。当你再次访问这个网站的时候,大部分的静态文件浏览器都已经缓存了,你可以直接拿来自己用,你会发现打开速度快了很多,这就是缓存的好处。强制缓存和协商缓存是针对静态文件资源的。它们之间有什么区别或联系?这里有一个前提:都是针对静态资源的!为什么只针对静态资源?接口数据不需要缓存吗?因为对于接口数据(api)来说,静态资源要大得多,不会轻易改变。比如前端单页面打包的bundle.js、chunkjs、css样式、字体文件、各种图片等,短时间内不会发生变化,不需要再次请求。请求直接保存在浏览器中后,下次可以快速访问。如何缓存动态数据?相比之下,接口数据是不可预测的,因为这些都是业务相关的,实时性是必须的。如果有些数据实时性要求不高,访问量比较大,可以在请求接口的方法上做一些调整,将接口返回的数据保存在内存中,直接从再次请求时的内存。可以实现类似下面的伪代码:/***获取年度最热排行榜前十名*缓存时间为一小时*@param{String}url*/functiongetHostList(){//判断是否有缓存是否过期(1h)//获取缓存中的数据并包装成promise}//第一个请求或缓存过期returnfetch('/getHostListApi').then(res=>{returnres.join();}).then(data=>{getHostList.cache={time:Date.now(),data};returndata;})}小知识:函数也是对象,可以给它添加其他属性!言归正传,强制缓存和协商缓存有什么区别和联系?主要有两点:1、触发顺序不同。首先判断文件是否过期(后面会讲解如何判断是否过期)。如果没有过期,就会触发强制缓存。浏览器直接读取本地文件。http状态码为200(frommemorycache)或(fromdiskcache)frommemorycache:在本地读取缓存。由于本次访问网站,部分文件已经加载到内存中,可以直接从内存中读取。关闭浏览器或标签页后,它会被清除。从内存缓存将出现。fromdistcache:从本地读取缓存,不在内存中,读取磁盘中的缓存文件。文件过期,触发协商缓存,发起请求询问服务器文件是否有更新,如果没有更新,浏览器会使用本地缓存文件,如果文件有更新,服务器会返回一个新文件传给客户端,并更新新的过期时间和缓存起来。2.强制缓存不需要访问服务器,协商缓存需要访问服务器。强制缓存是浏览器的自导自动行为。请求时检查文件是否过期,没有过期直接使用。协商缓存就是浏览器发现文件过期了,需要和服务器通信,让服务器判断是否过期。如果没有过期,仍然使用浏览器缓存。如果过期,则使用服务器新返回的文件。浏览器如何知道资源是否已过期?在请求的ResponseHeader中,我们熟悉两个header字段:expires和cache-control。expires是http1.0的产物,表示资源过期的绝对时间,但是每台机器本地时间不一样,会造成不必要的麻烦。Solidhttp1.1增加了cache-control来表示相对时间,从客户端收到资源的那一刻起,到过期需要多长时间(以秒为单位)。当expires和cache-control都存在时,cache-control的优先级更高。浏览器在请求资源之前,通过判断浏览器的本地时间和上一个接口返回的ResponseHeader中的expires和cache-control时间来判断是否过期。现在知道了判断资源是否过期,没有过期触发强制缓存的方法。通过上面的介绍,我们知道当资源过期时,会触发协商缓存,向服务端发送请求,询问资源是否有更新(变更),那么服务端如何知道资源是否更新已经升级了?如何判断一个资源是否更新?通过请求的ResponseHeader的两个字段记录:最后更新时间(last-modified)和文件标识符(ETag)。如何?首先,在一个请求中,服务器会在ResponseHeader中返回文件的最后修改时间:Last-Modified或者最新的文件标识符ETag。为什么Last-Modified还不够,还需要ETag?因为有些文件的更新时间虽然变了,但是内容没有变。所以用ETag来表示文件内容是否发生了变化,相当于一个版本号。ResponseHeader的内容如下:当下次发送相同的请求时,请求Header的内容如下:If-Modified-Since的值对应Last-Modified的值,If的值-None-Match对应ETag的值,服务器获取这两个值的组合根据自己的实际情况判断,如果还是没有变化,告诉浏览器(代码304)文件没有变化,你可以继续使用缓存中的资源,并updateexpires和cache-control,让文件在服务器设置的时间再次缓存。如果有变化,则将新资源返回给客户端(代码200),客户端再次缓存新资源。这就是强制缓存和协商缓存的全部内容。这只是一个简单的区分,让大家有个清晰简单的认识。下次面试官提问的时候,可以自己去摸索更多的细节。总结:强制性缓存和协商缓存都是针对静态资源的。动态资源缓存的方法可以参考上面的伪代码。强制缓存在前,协商缓存在后。强制缓存在资源未过期时触发,协商缓存在资源过期后触发。过期判断方法expires(绝对时间),cache-control(相对时间)判断资源是否更新(Last-Modified和ETag)。接下来我应该写什么?欢迎大家评论留言或指出错误~,谢谢!请大家不要忘记点赞、评论、收藏我。上期花絮:1.【困惑系列】一题:module.exports,exports,exports都是导出的。有什么不同?2.【宝珍】我的第一次webpack优化,首屏渲染从9s到1s