浏览器缓存保证让你轻松看懂

1,139 阅读7分钟

“这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

http缓存

当我们第一次进入一个网站的时候。
我们的浏览器需要去加载一些资源
比如果 html,css,img,js...
这些资源第一次肯定是需要加载的。
有些小伙伴可能会想:
如果第二次进入的时候。
那么我们需不需要去加载这些资源呢???

第二次不需要再次请求

当我们第二次请求这个网站的时候
我们就不需要再次请求这个网站已经请求过的资源了
这个时候我们可以使用第一次请求过的资源[这些资源将会缓存到我们的本地]
这样以来,我们网站的响应速度就会很快哦

01.png

缓存读取的顺序

想必小伙伴们已经清楚缓存了。
有些机智的想伙伴可能会想这样一个问题
缓存读取有限售顺序吗?还真有。

1==>先查找内存,如果内存中存在,从内存中加载;
2==>如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;
3==>如果硬盘中未查找到,那就进行网络请求;
加载到的资源缓存到硬盘和内存;
这就是缓存的读取顺序

如何设置缓存

在响应头中设置[Response Headers] cache-control: max-age=31536000
它的单位是s
31536000s=一年
如果我们不希望某一个文件缓存,我们可以将 cache-control:no-cache
这样浏览器就不会缓存了
如果没有设置 cache-control;同样不需要缓存。
当我们下一次在去请求这个网站的时候;
我们的浏览器回去检查max-age有没有过期
如果max-age过期了,就会重新去请求
如果max-age没有过期,则不会去重新请求,而是直接去使用本地之前的缓存

有的小伙伴会说前端怎么设置缓存???我想知道!!
真相很残酷,其实缓存并不是前端设置的。
而是后端去设置后否缓存,以及缓存的时间。

02.png

协商缓存中每个标识的具体含义

协商缓存:是服务端的一种缓存策略
当我们第二次发送求的时候,会告诉服务器请求资源以及[资源标识]

General中可以见下列状态的的变更

Status Code: 200  (from memory cache) [第一次后访问掘金]
不访问服务器,一般已经加载过该资源且缓存在了内存当中。
直接从内存中读取缓存。
浏览器关闭后,数据将不存在(资源被释放掉了)
再次打开相同的页面时,不会出现from memory cache。
而是出现Status Code: 200  (from disk cache )

Status Code: 200  (from disk cache )
不访问服务器,
已经在之前的某个时间加载过该资源,
直接从硬盘中读取缓存,关闭浏览器后,
数据依然存在,
此资源不会随着该页面的关闭而释放掉下次打开仍然会是from disk cache。

200 大小(如3.4k)
访问服务器,size显示为实际资源的大小


304 Not Modified
访问服务器,发现数据没有更新,服务器返回此状态码。
然后从缓存中读取数据。
这种在请求头中有两个请求参数:If-Modified-Since 和 If-None-Match

Status Code: 200 的变化过程

以谷歌浏览器为例,我们将缓存清空
第一次进入掘金这个网站
我们以js文件为例子。肯定在General头中看见的是
第一次是:Status Code: 200 []

第二次(不关浏览器后):出现的是==>Status Code: 200  (from memory cache) [内存中读取]
第二次(关闭浏览器后):出现的是==>Status Code: 200  (from disk cache )  [硬盘中读取]


第三次(不关浏览器后):出现的是==>Status Code: 200  (from memory cache) [内存中读取]
第三次(关闭浏览器后):出现的是==>Status Code: 200  (from disk cache )  [硬盘中读取]xx次与第二次和三次相同,在资源没有改变的情况下
如果资源改变了,跟第一次的相同

也就是说:
从来没有加载过
不关闭是 Status Code: 200  (from memory cache) [内存中读取]
关闭后是 Status Code: 200  (from disk cache )  [硬盘中读取]

内存缓存和硬盘[磁盘]缓存的区别

上面我们说了内存读取和硬盘中读取。

内存缓存(from memory cache)具有两个特点,分别是:
1==>快速读取。
内存缓存会将编译解析后的文件,直接存入该进程的内存中.
占据该进程一定的内存资源,以方便下次运行使用时的快速读取。
2==>时效性:缓存时效性很短,会随着进程的释放而释放

硬盘缓存(from disk cache)的两个特点
1==>硬盘缓存则是直接将缓存写入硬盘文件中,
读取缓存需要对该缓存存放的硬盘文件进行I/O操作,
然后重新解析该缓存内容,读取复杂,速度比内存缓存慢。
2==>时效性:缓存时效性很长,不会会随着进程的释放而释放。
除非用户手动删除或者磁盘被损坏了

浏览器会把哪些文件丢进内存中?哪些丢进硬盘中?

对于大文件来说,大概率是不存储在内存中的,反之优先。
当前系统内存使用率高的话,文件优先存储进硬盘。
在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,
那么当刷新页面时只需直接从内存缓存中读取(from memory cache);
而css文件则会存入硬盘文件中[惊喜不,意外不],
所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。 

08.png

为什么一般js和img会放到内存而缓存css放在硬盘中?

样式表一般在硬盘中,不会缓存到内存中。
因为CSS样式加载一次即可渲染出网页。
但是脚本却可能随时会执行。
如果脚本在磁盘当中,在执行该脚本需要从磁盘中取到内存当中来。
这样的IO开销是比较大的,有可能会导致浏览器失去响应。
因此,脚本一般在内存中。

07.png

不同浏览器资源加载策略

以上的数据及统计都是在chrome浏览器下进行的,
在Firefox下并没有from memory cache以及from disk cache的状态展现
相同的资源在chrome下是from disk/memory cache,
但是Firefox统统是304状态码,

06.png

协商缓存中的标识

标识有两种: Last-Modified 和 ETag 这两种

Last-Modified:是上一次的修改时间,在请求中可以看见
当我们发送请求的时候,会携带上资源标识,
如果 Last-Modified 的值与我们上一次修改的时间相同,则直接读取本地缓存
如果使用的是 Last-Modified,我们在请求头中携带的键名叫做 If-Modified-Since
当服务器看到接收到后,会比较 If-Modified-Since的值与Last-Modified是有一致
如果是一致,说明是最新资源,否者不是最新资源

ETag:资源对应的唯一字符串
我们发送请求的时候,会携带上If-Node—match这个标识
如果我们携带的 If-Node-match:xxxx与ETag的值相等
如果是相等,说明是最新资源,否者不是最新资源

ps: If-Modified-Since[在谷歌浏览器不可见,火狐浏览器的请求头中可以看见]

06.png

Last-Modified 和 ETag缓存的区别

Last-Modified 只能够精确到秒这个级别
如果每个一段时间都发重复生成,但是我们的内容是相同的,
Last-Modified会返回我们文件最后一次的修改时间。
也就是说虽然我们的内容是相同的,但是打包的时间发生了变化。
浏览器第二次就不会读取本地的缓存了【虽然内容是相同的】
而知需要服务器返回最新的资源【其实最新的资源和我们本地的是相同的】

ETag可以判断文件的内容是否相同,内容相同,返回304,使用缓存