前端缓存是什么
前端缓存一般用于缓存一些不常修改的常量数据或一些静态资源文件。大部分接口请求的数据都缓存在了服务端,方便统一管理缓存数据。前端做缓存可以缓解服务端的压力,减少带宽的占用,同时也可以提升前端的查询性能。
前端缓存可分为两大类:浏览器存储 和 HTTP 缓存 。
浏览器存储
浏览器存储的分类:
- Cookie
- WebStorage
- sessionStorage(会话存储)
- localStorage(本地存储)
WebStorage
WebStorage提供两种类型的API:localStorage
和 sessionStorage
。它们均继承自 Storage
类。
sessionStorage
sessionStorage 对象是 Storage 类型的一个实例,拥有 Storage 的所有属性和方法。
页面刷新不会影响 sessionStorage 对象中的数据;除 IE 之外,其他浏览器即使崩溃了,重启后也不会影响 sessionStorage 对象中的数据。
// 存储数据
sessionStorage.name = "ZZZZZ";
sessionStorage.setItem("name", "Zzzzz");
// 获取数据
console.log(sessionStorage.name); // ZZZZZ
console.log(sessionStorage.getItem("name")); // ZZZZZ
// 删除数据
delete sessionStorage.name;
sessionStorage.removeItem("name");
localStorage
localStorage 对象是 Storage 类型的一个实例,拥有 Storage 的所有属性和方法。
localStorage 对象用来:持久保存客户端的数据(数据保留到通过 JavaScript 删除或者是用户清除浏览器缓存)。
操作 localStorage 对象中的数据:
// 存储数据
localStorage.name01 = "Liuibang";
localStorage.setItem("name02", "Zhangliang");
// 获取数据
console.log(localStorage.name01); // Liuibang
console.log(localStorage.getItem("name02")); // Zhangliang
// 删除数据
delete localStorage.name01;
localStorage.removeItem("name02");
Cookie
Cookie 用来:存储客户端的 HTTP 状态信息。
Cookie 的特点:
-
同一个域名下的 cookie 是共享的。不利于 http 性能的提升,而且不同域名间会产生跨域。
-
数量受限,大小受限。不同的浏览器对 cookie 都有各自的数量限制,且每个 cookie 只能存储 4KB 大小的数据。
-
可以设置有效期。关闭浏览器后,没有设置有效期的 cookie 会被清掉,设置了有效期的 cookie 会继续生效,直到过期时自动清掉
小结
-
Cookie:
- 用来存储客户端的 HTTP 状态信息。
- 同一个域名下的 cookie 是共享的。不利于 http 性能的提升,而且不同域名间会产生跨域。
- 数量受限,大小受限。不同的浏览器对 cookie 都有各自的数量限制,且每个 cookie 只能存储 4KB 大小的数据。
- 可以设置有效期。关闭浏览器后,没有设置有效期的 cookie 会被清掉,设置了有效期的 cookie 会继续生效,直到过期时自动清掉。
-
sessionStorage(会话存储):
- 用于临时保存同一窗口(或标签页)的数据。在关闭窗口后这些数据会自动删除。
- 只能存储字符串。
- 不会产生跨域。
- 同步存储。
- 大小受限,最多只能存储 5M 。
-
localStorage(本地存储):
- 用来持久保存客户端的数据。只要不人为删除数据会一直在。
- 只能存储字符串。
- 不会产生跨域。
- 同步存储。
- 大小受限,最多只能存储 5M 。
HTTP 缓存
HTTP 缓存是通过设 置 HTTP Header 来实现的。
HTTP 缓存分类:
-
强缓存:在缓存期间不需要请求。
-
协商缓存:如果缓存过期了,就需要发起请求验证资源是否有更新。当浏览器发起请求验证资源时,如果资源没有做改变,那么服务端就会返回 304 状态 码,并且更新浏览器缓存有效期。
强缓存 与 协商缓存的对比:
- 共同点:都是从客户端缓存中读取资源。
- 区别是:强缓存不会发请求,协商缓存会发请求。
强缓存
强缓存指的是:先不向服务器发送请求,而是直接从缓存中读取资源。
若缓存有效,则状态码是 200
,并且 Size
显示 from disk cache
(硬盘缓存)或 from memory cache
(内存缓存)。若缓存已过期,才会向服务器发送请求。
强缓存的 2 种实现方式:
利用 Expires
或者 Cache-Control
这两个 HTTP Response Header
实现的,它们都用来表示资源在客户端缓存的有效期。
- Expires:Expires 属性是一个绝对时间。
- Cache-Control:Cache-Control 属性是一个相对时间,即一个过期时间大小,与协商缓存一样。可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。
Expires
Expires 属性是一个绝对时间。
Expires 缓存的弊端:
受限于本地时间,如果修改了本地时间,可能会造成缓存失效。到期时间由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。
Cache-Control
HTTP 1.1 的版本,使用 Cache-Control 替代了 Expires 做浏览器的强制缓存。
Cache-Control 属性是一个相对时间,即一个过期时间大小,与协商缓存一样。可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。
Cache-Control 可以在 请求头 或者 响应头 中设置,并且可以组合使用多种指令:
常见的取值有:private、public、no-cache、max-age,no-store。 默认取值为:private。
Cache-Control 多种指令的含义:
- private: 客户端可以缓存。
- public: 客户端和代理服务器都可缓存。
- max-age=xxx: 缓存的内容将在 xxx 秒后失效,需要重新请求。
- s-max-age=xxx: 缓存的内容将在 xxx 秒后失效,需要重新请求。
- no-cache: 需要使用协商缓存来验证缓存数据。
- no-store: 所有内容都不会缓存(强制缓存、协商缓存都不会触发)。
- max-stale=xx:xxx秒内即使缓存过期,也使用该缓存。
- min-fresh=xx: 希望在xx秒内获取获取最新响应。
用 Cache-Control
实现强缓存的流程如下:
-
当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
-
浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则请求服务器;
-
服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。
协商缓存
协商缓存指的是:与服务端协商之后,通过协商结果来判断是否使用本地缓存。
协商缓存的 2 种实现方式:
- Last-Modified/If-Modified-Since:
- ETag/If-None-Match:
实现流程如下:
-
当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在
Response
头部加上ETag
唯一标识,这个唯一标识的值是根据当前请求的资源生成的; -
当浏览器再次请求访问服务器中的该资源时,会在
Request
头部加上If-None-Match
字段,该字段的值就是Response
头部加上ETag
唯一标识; -
服务器再次收到请求后,会根据请求中的
If-None-Match
值与当前请求的资源生成的唯一标识进行比较,如果值相等,则返回304 Not Modified
,如果不相等,则在Response
头部加上新的ETag
唯一标识,并返回200
状态码和请求的资源; -
如果浏览器收到
304
的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。