前端缓存是每个前端程序员成长过程中都要面对的问题,它在极大优化和改进你的项目的同时,也会带来其他问题。大多数前端程序员也有一些关于缓存的知识,比如强缓存、协商缓存、cookie,但我认为大多数前端程序员并不了解缓存机制。接下来我们将深入理解缓存机制和缓存时间公式,并讲解如何合理利用缓存机制来提高优化。我们将前端缓存分为两部分:HTTP 缓存和浏览器缓存。
HTTP 缓存
HTTP 是一种超文本传输协议,通常在TCP 上运行。从浏览器网络中可以看到,HTTP分为两部分:响应头(response headers)和请求头(request headers)。
以下标头字段与缓存相关。
expires
首先,让我们看一下MDN 过期日期的概述。
响应标头包含响应被视为过期的日期/时间。
注意:如果响应具有带有指令max-age 或s-maxage 的Cache-Control 标头,则将忽略Expires 标头。
过期时间: 2024 年4 月24 日星期三14:27:26 GMT
Cache-Control
Cache-Control是HTTP/1.1定义的缓存字段。可以以各种组合使用,例如max-age、s-maxage、公共/私有、无缓存/无存储。
Cache-Control: max-age=3600,s-maxage=3600,公共
max-age 相对于当前时间(以秒为单位)。如果设置了max-age,则过期时间将被覆盖,并且max-age 优先。
s-maxage 和max-age 之间的区别在于它仅适用于公共缓存服务器。例如,资源从源服务器发送,由中间代理服务器接收并缓存。
公共意味着该资源可以缓存在任何节点上,而私有意味着只能提供给客户端进行缓存。当设置为私有时,s-maxage 被禁用。
。
强缓存
强缓存的具体流程如下:
上面我们介绍了过期时间设置为根据客户端时间确定的绝对时间。如果资源缓存到其到期日期为2024 年4 月31 日,则到期日期将不准确。如果过期日期发生变化,则在访问资产时会重新请求服务器获取最新数据。
虽然max-age是一个相对时间,其值是以秒为单位的时间,但是max-age也会不准确。
那么,浏览器如何判断资源缓存是否有效呢?这里我们介绍一下资源新鲜度的计算公式。
我们以日常生活中食物的新鲜度为例。
食品是否新鲜=(生产日期+保质期)当前日期
那么你也可以用这个公式来判断缓存是否是新的。
缓存是否新建=(创建时间+ 过期时间|| max-age) 缓存年龄
这里的创建时间可以理解为服务器返回资源的时间,和过期一样是一个绝对时间。
缓存周期=响应周期+传输延迟时间+缓存驻留时间
响应寿命
有两种方法可以获取响应的年龄:
max(0, 响应时间- 日期时间) 年龄
responseTime:是指客户端收到响应的时间。
dateTime: 指服务器创建资源的时间。
Age:是响应头中的一个字段,通常以秒为单位。
传输延迟时间
传输延迟时间=客户端收到响应的时间-请求时间
停留时间
停留时间=当前客户端时间-客户端收到响应的时间
所以max-age 失败的问题是它也使用了客户端的时间。
协商缓存
协商缓存的具体流程如下:
如上所示,协商缓存由两个字段决定:Etag 和Last-Modified。那么Etag标志是如何生成的呢?
可以在Node中查看etag第三方库。
该库使用isState 方法来确定文件的格式。对于文件格式,请使用第一种方法,该方法根据文件内容和修改时间生成Etag。
第二种方法:根据文件内容、哈希值、内容长度生成Etag。
浏览器缓存
如果您访问掘金网站并查看您的网络,您会看到有一个“大小”列,有些列没有大小,但被标记为“磁盘缓存”、“内存缓存”等。
内存缓存翻译,顾名思义,是保存在内存中的,所以可以看到时间一栏是0ms。虽然缓存被清除,但是内存大小非常有限,所以如果要存储大量资源,还是应该使用磁盘缓存。
磁盘缓存是一种存储在计算机磁盘上的缓存,与内存缓存相反,这意味着读取时间更长。 1 毫秒。
缓存获取顺序
浏览器首先搜索内存缓存,如果内存缓存不存在,则再搜索回磁盘缓存。磁盘缓存中的资源。如果磁盘缓存不存在,则发出网络请求,并将最新资源存储到内存或磁盘缓存中。
缓存存储优先级
浏览器如何决定将资源存储在内存缓存还是磁盘缓存中?
当您打开掘金网站时,您会看到除了从内存中检索的Base64 图像之外,大多数其他资源都是从磁盘中检索的。
js 文件,你需要小心。可以看到下面的js文件有的缓存到磁盘,有的缓存到内存。为什么是这样?
启动器列指示资源的加载位置。如果单击某列从内存中检索资源,您将看到该资源在HTML 渲染阶段加载。包括以下代码。
!DOCTYPE html
html lang=\’en\’
头
元字符集=\’UTF-8\’/
标题文档/标题
脚本src=\’https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js\’/script
/头
身体
像div id=\’root\’这样加载的js资源更有可能存储在内存/div中。
/身体
/html
内存放弃的是异步资源,不会缓存在内存中。
上图中,可以看到initiator列的值为(index):50,但它仍然缓存在内存中,所以可以点击查看代码如下。
这个js文件是通过动态创建script标签来动态部署的。
Preload 与 Prefetch
预加载和预取也会影响浏览器缓存资源的加载。
预加载称为预加载,用在链接标签中,指在页面加载后、渲染机制干预之前立即需要哪些资源。
链接rel=\’预加载\’ href=\’//lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/0358ea0.js\’ as=\’script\’
当你使用preload来预加载资源时,这些资源总是从磁盘缓存中读取。
prefetch的意思是预取,浏览器利用空闲时间下载资源并存储到缓存中。
链接rel=\’prefretch\’ href=\’//lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/0358ea0.js\’
使用预取加载的资源可能会在您更新页面时从磁盘缓存中读取,并且当您跳转到使用它的页面时,该资源将直接从磁盘加载。
使用no-store 意味着资源不被缓存。使用no-cache 意味着告诉(代理)服务器不要直接使用缓存,而是在响应标头中返回时向源服务器发起请求。这意味着客户端可以缓存资源,但必须缓存它。服务器在使用缓存资源之前验证其有效性,这对于需要在每次访问时进行身份验证的应用程序非常有用。
当然,您也可以在代码中添加元标记来修改资源的请求标头。
meta http-equiv=\’缓存控制\’ content=\’no-cache\’ /
示例
到这里我们就启动了nestjs服务。 getdata接口缓存10秒。这是代码:
@Get(\’/getdata\’)
getData(@Response() res: Res) {
return res.set({ \’过期\’: new Date(Date.now() + 10).toUTCString() }).json({
list: new Array(1000000).fill(1).map((item,index)=({index,item:\’index\’+index}))
});我
}
第一个请求花费了334 毫秒。
第二个请求花费了163 毫秒,因为它使用了磁盘缓存,使其速度提高了近50%。
接下来看看是否可以使用Cache-Control来覆盖Exprie。修改getdata接口如下,将Cache-Control设置为1s。如果刷新页面,就会看到getdata接口没有被缓存,每次都会向服务器发送请求。
@Get(\’/getdata\’)
getData(@Response() res: Res) {
return res.set({ \’Expires\’: new Date(Date.now() + 10).toUTCString(), \’Cache-Control\’: 1 }).json({
list: new Array(1000000).fill(1).map((item,index)=({index,item:\’index\’+index}))
});
}
细心的同学应该注意到,清除缓存后第一次和第二次请求的大小是不同的。为什么是这样?
右键F12打开刷新按钮,点击“清除缓存并硬重新加载”。
打开大请求行可以更轻松地查看大小。勾选后,Size下会出现两行,第一行是请求内容的大小,第二行是实际大小。
刷新后,你会看到大小变成了283B。
带着这个问题,让我们仔细看看浏览器压缩。 HTTP2和HTTP3的压缩算法几乎相同。我们来看看HTTP2(HPACK)压缩算法。
HTTP2 HPACK压缩算法
HPACK压缩算法大致分为静态哈夫曼(Huffman)压缩和动态哈夫曼压缩。所谓静态压缩是指根据HTTP提供的静态字典表查找对应的请求头字段并存储对应的索引值。显着减少内部压力空间。
动态压缩是在同一会话级别执行的,其中第一个请求的响应包含类似{list: [1, 2, 3]} 的消息,并且其他后续请求的响应也存储在该表中。仅返回该表头在动态表中的索引以达到压缩目的。
如果您想了解更多关于霍夫曼算法的原理,请访问并阅读此博客。
Last-Modified 与 If-Modified-Since
Last-Modified表示属于响应头字段的资源的最后修改时间。当浏览器第一次收到从服务器返回的资源的Last-Modified 值时,它会保存该值,并在下次访问该资源时使用If-Modified-Since 请求标头将其发送到服务器。检查资源是否过期。
亚穆尔
复制代码
最后修改时间: 2021 年5 月14 日星期五17:23:13 GMT
If-Modified-Since: 2021 年5 月14 日星期五17:23:13 GMT
如果资源在If-Modified-Since 字段中指定的时间内尚未更新,服务器将使用状态代码304 Not Modified 进行响应。
Etag 与 If-None-Match
Etag代码是资源的唯一标识符。同样,浏览器第一次收到服务器返回的Etag值后,访问时会持有If-None。下次向服务器发送Match请求头来检查资源是否过期。
Etag:\’29322-09SpAhH3nXWd8KIVqB10hSSz66\’
如果-无-匹配:\’29322-09SpAhH3nXWd8KIVqB10hSSz66\’
如果两者不相同,则说明服务器资源已更新,服务器返回该资源最新的Etag值。
#以上详细了解前端缓存的相关内容来源网络,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91214.html