前端获取浏览器标识_[前端优化]浏览器缓存策略

前端性能优化优先级最高的便是浏览器缓存策略

提到前端性能优化,有一个问题就怎么也绕不开

那就是,提升首屏加载速度.

这时候,很多人都会率先想到服务端渲染,或者优化构建包这些常用的解决办法.

但是这些办法往往都不是最优解,因为这些方法往往只能有限的提升首屏首次记载的速度,且优化效果往往不是特别明显.

那么我们还有没有更好的方法呢?

肯定是有的呀~

其实浏览器早就为我们提供了一份缓存机制,我们完全可以利用浏览器缓存机制来巨幅提高加载速度~


废话终于说完了,我们直接来看干货.

首先我们来聊一下缓存的优先级:

当客户端需要请求一个服务端资源的时候,会率先检查浏览器中是否有缓存,没有则直接调取接口.

若有,则会检查缓存是否过期,判断是否过期的方法有两种.

  1. Expires(到期时间)(http1.0规则下的响应头)

如果服务端返回的response header中含有 Expires字段,且这个字段应该是一个时间戳,类似

Expires: Wed, 25 Oct 2019 16:48:00 GMT

如果客户端此次发送请求的时间在Expires之前,则会直接触发缓存,不再去发起请求.

2. Cache-Control(缓存控制)(http1.1规则下的响应头)

Cache-Control同样是服务端返回的一个响应头,他有几个选项可供使用:

1d400e860ff2a3efa660b7bb0ac81fbc.png

我们实际开发中比较常用的一般是public,private和max-age.

72221671b718f07d00f8fd6c9249d021.png

尤其是max-age最常出现,举个栗子:

当我们使用诸如webpack之类的前端构建工具时,node_module下的工具包,例如vue,react,lodash等等

这些包都有一个显著的特点,就是我们一旦决定使用,短期内就不会有更新版本的可能了

也就是说,我们没有必要每次都向服务端发送请求,将这些不常变动的包下载下来,那么我们就可以将这些包单独打包,部署至服务端,在服务端配置响应头Cache-Control: max-age=100000;

值得注意的是,如果我们使用这种缓存策略,我们的第三方包就不可以变更名字,因为一旦包的名字发生了变化,包的请求就会变成一个新的请求,不会触发cache-control的缓存了.

而以上两种缓存方式,被总称为强缓存,且Cache-Control的优先级要优于Expires~

其实这个概念蛮好理解的,因为强缓存一旦触发,就不会再向服务端发送请求了,着实是非常的强力~

然而这个时候有好事的同学肯定会问: 那么缓存都是缓存在哪里呀?

这个问题问的很好(qian er),其实浏览器的缓存一般都存放在内存或者磁盘中.

1.内存缓存(memory cache)

一般将脚本,图片,字体等常常和页面产生交互的部分存放在内存中,原因也很简单,比较利于性能提升.

2.磁盘内存(disk cache)

一般将css等这些不经常变动的数据放在磁盘中进行缓存.

然而,既然有了之前比较欠的提问,相信肯定会有更欠的同学会问:

既然内存和磁盘缓存这么厉害,我们要怎么配置呢?

答案也非常简单,就是我们无法配置,这个是浏览器的默认行为,我们要做的就是把它记下来,将来才可以面对面试官郎朗的吹着牛啤~


好像扯的有点远,我们回归正题,之前我们讲了不需要发送请求的强缓存,现在我们再来讲一下更加重要的协商缓存,也就是需要和服务端交互的缓存机制.

协商缓存

顾名思义,协商缓存就是客户端在没有匹配到强缓存的前提下,向服务端发起了请求,而服务端则会使用两种方式来判断.

请求的资源是否在上一次请求和这一次请求之间发生过变化.

如果发生了变化则正常发起200响应,反之则发起304响应,直接触发协商缓存.

这两种方法分别是:

  1. Last Modified 与 If-Modified-Since(http1.0响应头和请求头)

服务端在上一次响应客户端响应时,可能会返回一个Lase Modified的响应头,对应的值是一个时间戳,例如:

Last-Modified: Wed, 25 Oct 2019 16:48:00 GMT

这个字段对应的时间代表服务端该资源的最后一次更改时间,当客户端再一次请求该资源时,浏览器会自动为请求添加If-Modified-Since请求头,且该请求头携带上一次Last-Modified的值.

服务端接收到If-Modified-Since请求头后,会和服务端所储存的该资源最后修改时间作对比,如果没有任何变化,服务端会响应304,客户端就会直接从缓存获取数据.

如果不相等,则说明两次请求间服务端已经修改过该资源,则会响应200,并重新返回数据传输给客户端.

值得一提的是,如果我们并没有配置缓存策略,浏览器会将响应头中的Date减去Last-Modified再乘以0.1,作为我们的资源缓存时间.

但是Last Modified&If-Modified-Since组合由于是非常老的http1.0的规则,也是有着比较显著的缺点的:

这种方法侦测改变的时间的最小单位为1s,这意味着如果在1s的时间内,请求的资源发生了改变,也会正常触发缓存,导致客户端无法获取到最新资源.

当然,我们也有更好的方式来处理这个问题那就是下面要介绍的Etag.

2. Etag与If-None-Match(http1.1响应头和请求头)

Etag是服务端根据请求资源的内容所生成的一种类似于Token的标识,而下次发起对该资源的请求时,请求头会携带If-None-Match字段,该字段携带着上次服务端返回的Etag的值.

服务端接收到If-None-Match之后,会和该资源的标识进行对比,如果相同则认为资源未发生变化,响应304,客户端自动使用资源缓存

如果发现两次的标识不相同,则会响应200,且发送最新的资源.

Etag&If-None-Match的缓存策略优先级要比Last-Modify&If-Modified-Since高,且缓存精度也更高,不会出现Last-Modified&If-Modified-Since在1s中内失去效应的情况.

但是,由于Etag需要服务端使用特定算法判断资源变化情况,所以所占用资源较多,性能上不如Last-Modified&If-Modified-Since这种判断时间戳的方式快.

不过从目前的开发形式来看,我还是更推荐使用Etag,一方面如今的服务端性能大大提高.

另一方面,现在大多数服务端都采用了负载均衡策略,可能导致不同虚拟主机返回的Last-Modified时间戳不一致,导致对比失败~

如果想了解更多关于http的知识,可以去看下MDN的讲解,如果有同学想要尝试,建议使用node.js搭建一个本地服务器,最近我对node也越来越感兴趣,后面会和大家多分享node的一些知识.

最后,附一张图,便于大家调试浏览器缓存~

c78c775358182fdf2f00a5b8baf44074.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值