十分钟弄懂强缓存和协商缓存(绝对够通俗,看了壁咚)

lxf2023-03-13 08:16:01

强缓存 协商缓存

强缓存和协商缓存是前端面试高频,下面采用了通俗易懂的方式来讲解它

强缓存

基本流程

当一个浏览器第一次访问一个网站的时候,向该网站的服务器发送请求。如果服务端觉得浏览器请求的资源应该被缓存下来时 比如图片,CSS文件等不常更改的资源,没有必要在 HTTP 响应中频繁携带,就会在 HTTP 响应里面添加一个响应头 Cache-Control:max-age=1200(即缓存有效时间为1200s)。这会让浏览器自动将该请求的资源缓存到本地。

下一次请求该资源时,浏览器先看本地缓存的资源有没有过期,没过期的话直接使用该资源,不发送请求,且返回 Status Code:200 OK,但是会添加上(from memory cachefrom disk memory)的标识,表示该文件是从缓存中拿到的,没有向服务端发送请求。

如果过期了且没有协商缓存(可以先跳过这个协商缓存,下面会讲)就向服务端发送请求索要该资源,服务端依然是根据该资源的特性判断要不要缓存,即要不要加 Cache-Control 响应头。

整个过程都是由 服务端控制,浏览器要不要缓存取决于 HTTP 响应头有没有设置 Cache-Control,且取值不为 no-store(no-store 表示不缓存)。

注意:
(1)强缓存不发送请求,直接从本地缓存读取资源并返回 Status Code: 200 OK;
(2)from memory cache 表示资源是从内存当中获取的,浏览器关闭后该资源内存会被释放;from disk memory 表示资源是从硬盘中读取的,关掉浏览器资源依然在。

协商缓存(又名对比缓存)

基本流程

当一个浏览器第一次访问一个网站的时候,向该网站的服务器发送请求。服务器返回资源和资源的标识。浏览器会把该资源和该标识缓存到本地。

下一次请求该资源时,浏览器会把该资源标识带上,服务器就会对该标识对应的资源进行判断:
(1)如果该资源发生了修改,已不是原来的版本,那么服务器就会返回最新的资源和新的资源标识,状态码为200,表示请求成功。
(2)如果该资源距离上一次请求并没有发生改变,则返回304,告诉浏览器可以直接使用本地缓存的资源,响应时就无需携带资源。

协商缓存中的资源标识(2 种)

Last-Modified:资源上一次修改的时间

服务端可以根据资源上一次修改的时间判断出该资源是否为最新。

具体过程:浏览器第一次请求资源时,服务端会返回资源和资源标识 last-Modified;
当浏览器下一次请求该资源时,会带上这个标识,请求头键名为:If-Modified-Since,键值为第一次访问时服务端返回的那个修改时间标识;
该请求发送到服务端之后,服务端会检查该值跟所请求资源的最近修改时间是否为一致:
(1)如果一致直接返回304
(2)如果不一致返回200 + 最新资源 + 最新的资源修改时间


ETag:资源对应的唯一字符串

服务端可以根据唯一的字符串是否发生变化判断该资源是否为最新。

具体过程:浏览器第一次请求资源时,服务端会返回资源和资源标识 ETag 字符串;
当浏览器下一次请求该资源时,会带上这个字符串,请求头的键名为:If-None-Match,键值为第一次访问时服务端返回的 ETag 字符串;
该请求发送到服务端之后,服务端会检查该值跟所请求资源的标识字符串是否一致:
(1)如果一致说明文件内容没有发生变化,直接返回304;
(2)如果不一致返回200 + 最新资源 + 最新的 ETag字符串。

ETag 字符串不一致说明,在两次访问文件资源期间,对文件做了修改,访问了修改文件的接口,后端将最新修改的内容生成一个新的字符串,保存了起来。


Last-Modified 和 ETag 比较

我们已经了解了这两种不同的方式,那么我们要选择哪一种呢?

优先使用 ETag,原因如下:

Last-Modified 只精确到秒级;

Last-Modified 标识即使文件内容相同,但是只要修改时间发生变化,都会再次返回该资源,而 ETag 可以判断出文件内容是否相同,相同则直接返回304,缓存策略更佳。

如果使用的是 Last-Modified ,比如文件A加上了一段文字并保存,然后又把这段文字删除后再保存。此时尽管资源的内容不变,但是资源的修改时间发生了变化,服务端依然会返回该资源,而不是返回304。
如果使用的是 ETag 字符串,那么文件A的内容其实是没有发生变化的,浏览器依然会用本地的缓存。

总结

当浏览器请求一个资源时,浏览器会先判断本地有没有缓存

没有缓存则直接发送请求,拿到最新的资源;如果有缓存,就判断是否过期

如果没过期就直接用本地缓存的资源,如果过期了就再看有没有 Last-Modified或 ETag

没有的话就直接请求资源,有的话就带上该标识去往服务端,服务端会根据该资源的修改情况返回200或304;

最后拿到数据,渲染页面