缓存分类
分类一
- HTTP缓存
- 浏览器缓存
其中 HTTP
缓存是在 HTTP
请求传输时用到的缓存,主要在服务器代码上设置;而浏览器缓存则主要由前端开发在前端 js
上进行设置。
浏览器与服务器通信的方式为应答模式,即是:浏览器发起 HTTP
请求 – 服务器响应该请求。那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中 HTTP
头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中。
分类二
- 强制缓存
- 协商缓存(也叫对比缓存)
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果,强制缓存的情况主要有三种。
① 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致)
② 存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存
③ 存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
那么强制缓存的缓存规则是什么?
当浏览器向服务器发起请求时,服务器会将缓存规则放入 HTTP
响应报文的 HTTP
头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是 Expires
和 Cache-Control
,其中 Cache-Control
优先级比 Expires
高。
Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义。
Cache-Control 的取值
在HTTP/1.1中,Cache-Control
是最重要的规则,主要用于控制网页缓存,主要取值为:
-
public:所有内容都将被缓存(客户端和代理服务器都可缓存)
-
private:所有内容只有客户端可以缓存,Cache-Control的默认取值
-
no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
-
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
-
max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效
那缓存存到哪里了呢?
- disk cache(硬盘中的缓存)
- memory cache(内存中的缓存)
浏览器读取缓存的顺序为 memory –> disk –> 服务器请求
。
在缓存领域,还有一个是
service worker
;service worker
是在你手动设置了要缓存哪些文件时才会生效,而且可以离线使用缓存的文件,很厉害的,但是这里我们不做过多讲解。
内存缓存具有两个特点,分别是速度快和时间限制。
硬盘缓存读取速度比内存缓存要慢一些。
那这里就有一个疑问:强制缓存,什么时候存到 memory cache , 什么时候存在 disk cache;存储位置的规则是什么?
几乎所有的网络请求资源都会被浏览器自动加入到 memory cache
中。但是也正因为数量很大但是浏览器占用的内存不能无限扩大这样两个因素,memory cache
注定只能是个“短期存储”。常规情况下,浏览器的 TAB 关闭后该次浏览的 memory cache
便告失效 (为了给其他 TAB 腾出位置)。而如果极端情况下 (例如一个页面的缓存就占用了超级多的内存),那可能在 TAB 没关闭之前,排在前面的缓存就已经失效了。
但如果你真的不想让一个资源进入缓存,就连短期也不行,那就需要使用 no-store
。存在这个头部配置的话,即便是 memory cache
也不会存储,自然也不会从中读取了。
disk cache
会严格根据 HTTP 头信息中的各类字段来判定哪些资源可以缓存,哪些资源不可以缓存;哪些资源是仍然可用的,哪些资源是过时需要重新请求的。当命中缓存之后,浏览器会从硬盘中读取资源,虽然比起从内存中读取慢了一些,但比起网络请求还是快了不少的。绝大部分的缓存都来自 disk cache
。
那协商缓存的缓存规则是什么?
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
① 协商缓存生效,请求返回状态为304,不返回请求结果
② 协商缓存失效,请求返回状态为200和请求结果
协商缓存的标识也是在响应报文的 HTTP
头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有
Last-Modified / If-Modified-Since
和 Etag / If-None-Match
其中 Etag / If-None-Match
的优先级比 Last-Modified / If-Modified-Since
高。
Last-Modified / If-Modified-Since
Last-Modified
是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。
If-Modified-Since
则是客户端再次发起该请求时,携带上次请求返回的 Last-Modified
值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有 If-Modified-Since
字段,则会根据 If-Modified-Since
的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于 If-Modified-Since
的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件。
Etag / If-None-Match
Etag
是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。
If-None-Match
是客户端再次发起该请求时,携带上次请求返回的唯一标识 Etag
值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有 If-None-Match
,则会根据 If-None-Match
的字段值与该资源在服务器的 Etag
值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。
Etag / If-None-Match
优先级高于Last-Modified / If-Modified-Since
,同时存在则只有 Etag / If-None-Match
生效。对于协商缓存,使用 Ctrl+F5
强制刷新可以使得缓存无效。但是对于强缓存,在未过期时,必须更新资源路径才能发起新的请求(更改了路径相当于是另一个资源了,这也是前端工程化中常用到的技巧)
总结
强制缓存优先于协商缓存进行,若强制缓存(Expires
和 Cache-Control
)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since
和 Etag / If-None-Match
),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回 304
,继续使用缓存。
扩展学习
本地存储小容量
- Cookie主要用于用户信息的存储,Cookie的内容可以自动在请求的时候被传递给服务器。
- LocalStorage的数据将一直保存在浏览器内,直到用户清除浏览器缓存数据为止。
- SessionStorage的其他属性同LocalStorage,只不过它的生命周期同标签页的生命周期,当标签页被关闭时,SessionStorage也会被清除。
本地存储大容量
- WebSql和IndexDB主要用在前端有大容量存储需求的页面上,例如,在线编辑浏览器或者网页邮箱。
往返缓存
往返缓存又称为 BFCache
,是浏览器在前进后退按钮上为了提升历史页面的渲染速度的一种策略。该策略具体表现为,当用户前往新页面时,将当前页面的浏览器 DOM
状态保存到 bfcache
中;当用户点击后退按钮的时候,将页面直接从 bfcache
中加载,节省了网络请求的时间。
-----------------(正文完)------------------
前端学习交流群,想进来面基的,可以加群:
或者手动search群号:685486827,832485817;
-------------------------------- (完)--------------------------------------
我的:
个人网站: https://neveryu.github.io/neveryu/
Github: https://github.com/Neveryu
新浪微博: https://weibo.com/Neveryu
更多学习资源请关注我的新浪微博…