前端缓存机制
浏览器缓存
场景:
首先我们需要知道JS中的变量有这样的问题:变量只在当前的会话期内有效。即只要刷新页面,之前存储的变量就被回收了。那么我们如何让之前所存储的变量在刷新页面之后还存在呢,
看个案例:
本地存储的好处显而易见,一是避免取回数据前页面一片空白,如果不需要最新数据也可以减少向服务端请求的次数,从而减少用户等待从服务器获取数据的时间,二是网络状态不佳时仍可以显示离线数据。
1.cookie
特点:
- cookie有数量与大小的限制
数量在50个左右 大小在4kb左右
- cookie的存储时间非常灵活
- cookie不光可以服务器设置(用set-cookie),也可以客户端设置。
写入方式: document.cookie = key=value;key1=value1;
添加到
request header 中是「浏览器的行为」,存储在cookie的数据每次都会被浏览器自动放在http请求中。因此,如果这些数据不是每次都要发给服务器的话,这样做无疑会增加网络流量,这也是cookie的缺点之一。为了避免这点,我们必须考虑什么样的数据才应该放在cookie中,而不是滥用cookie。每次请求都需要携带的信息,最典型的就是身份验证了,其他的大多信息都不适合放在cookie中。缺点:
- 安全性:由于cookie在HTTP中是明文传递的,其中包含的数据都可以被他人访问,可能会被篡改、盗用。
- 大小限制:cookie的大小限制在4KB左右,若要做大量存储显然不是理想的选择。
- 增加流量:cookie每次请求都会被自动添加到Request Header中,无形中增加了流量。cookie信息越大,对服务器请求的时间也越长。
因此要慎用cookie,不要在cookie中存储重要和敏感的数据。
2.localStorage本地存储
设置 localStorage.setItem(key, value)获取 localStorage.getItem(key)移除指定项 localStorage.removeItem(key)移除所有项 localStorage.clear()需要注意的是:localStorage 只能存 string,所以取出来时需要用
JSON.parse()- 优点:兼容性中等,几乎现代的浏览器都支持,没有过期时间限制,永久存储,永不失效,即只要浏览器不卸载,不去手动删除,数据就会一直存在
- 缺点:存在大小限制,IE9,IE10 不支持
3.sessionStorage会话存储
使用方式同
localStorage,不同的是生命周期- 优点:临时,关闭页面标签自动回收,不同的两个标签页面的 sessionStorage 是不共享的
- 缺点:不能存储持久化的东西 。IE不支持 SessionStorage
使用注意事项:
- 使用前要判断浏览器是否支持
- 写入数据时候,需要异常处理,避免超出容量抛错
- 避免用它们存储系统中的敏感数据
不是什么数据都适合放在 cookie、localStorage、sessionStorage 中的,因为只要打开控制台,就可以随意修改它们的值。
- 过期控制:localstorage 没有过期时间限制,如果需要有过期限制,需要自己添加过期的业务处理机制
- key的唯一性,如果有重复key,会被覆盖
- 子域名之间不能共享存储数据
-
indexedDB Database
一种能在浏览器中持久的存储结构化数据的数据库,并且为 web 应用提供了丰富的查询能力
- IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。
- 一般来说不少于 250MB,甚至没有上限
(1)键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
(2)异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
(3)支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
(4)同源限制 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
(5)储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
(6)支持二进制储存。 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
indexedDB 提供了类似数据库风格的数据存储和使用方式, 很强大,支持所有、事物处理和健壮的查询功能。当需要存储大量数据时,indexedDB 就明显的更适合了,但它的 API 也相对比较复杂
-
BFcache
后退/前进缓存, 是一种浏览器优化,可实现即时的后退和前进导航。它显著改善了用户的浏览体验,尤其是那些网络或设备速度较慢的用户。
不支持bfc时:将启动一个新的请求来加载上一个页面,并且,根据该页面针对重复访问的优化程度,浏览器可能需要重新下载、重新解析和重新执行刚下载的部分(或全部)资源。
开启了bfc时:加载上一个页面基本上是即时的,因为整个页面可以从内存中恢复,而不必访问网络。
总结:
| 特性 | Cookie | localStorage | sessionStorage |
| 数据的生命期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 除非被清除,否则永久保存 | 仅在当前会话下有效,关闭页面或浏览器后被清除 |
| 存放数据大小 | 4K左右 | 一般为5MB-10M | |
| 与服务器端通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 | |
| 语法 | 复杂 | 简易 | |
浏览器无痕模式
打开一个登录的系统,复制链接到无痕模式下,存储的信息是不被共享的
https://www.nothingprivate.ml/
HTTP缓存
HTTP缓存有多种规则,根据是否需要重新向服务器发起请求来分类,我将其分为两大类(强制缓存,协商缓存)
-
强缓存与协商缓存
用户说:我现在需要a.css,你们帮我拿回来 强缓存: 稍等,我找下我这里有没有关于a.css的备份,找到了。(消耗0kb流量) 协商缓存: 我这里也有备份,不过我得问下服务端这个备份是不是最新款,发送请求头(1kb流量)。服务端回复(1kb流量)响应头则使用本地备份,若没有则使用服务器返回的最新数据。-
disk cache 和memory cache
jq资源(来自内存缓存),Css 来自磁盘缓存
- 200(来自内存缓存)
from memory cache
- 高效,读取内存中的数据比磁盘快;缓存持续性短,会随着进程的释放而释放;关闭 Tab 页面,内存中的缓存也就被释放了。也就是浏览器关闭以后,数据将不存在。
- 200(来自磁盘缓存)
from disk cache
派生资源(内嵌的图片或者脚本链接)当杀死进程时,数据还是存在。
目前Webkit资源分成两类,一类是主资源,比如HTML页面,一类是派生资源,比如HTML页面中内嵌的图片或者脚本链接
| memory cache(内存缓存) | disk cache(磁盘缓存) | |
| 相同点 | 只能存储一些派生类资源文件 | 只能存储一些派生类资源文件 |
| 不同点 | 退出进程时数据会被清除 | 退出进程时数据不会被清除 |
| 存储资源 | 一般脚本、字体、图片会存在内存当中 | 一般非脚本会存在磁盘缓存,比如css |
大部分js之类的脚本,随时可能会执行,如果脚本在磁盘当中,我们在执行脚本的时候需要从磁盘取到内存中来,这样IO开销就很大了,有可能导致浏览器失去响应。
浏览器会把哪些文件丢进内存(Memory Cache)中?哪些丢进磁盘(Disk Cache)中?
对于大文件来说,大概率是存储在磁盘中的,反之则存储到内存中
当前系统内存使用率高的话,文件优先存储进磁盘
最终决定使用哪种缓存的应该是客户端,也就是浏览器了。浏览器对于缓存什么策略或者机制?
三级缓存原理
1. 先去内存看,如果有,直接加载
2. 如果内存没有,则去硬盘获取,如果有直接加载
3. 如果硬盘也没有,那么就进行网络请求
4. 加载到的资源缓存到硬盘和内存
- 304
Not Modified请求资源与本地缓存相同,未修改
访问服务器,发现数据没有更新,服务器返回此状态码。然后从缓存中读取数据。
| 502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 |
| 503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
| 504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
| 401 | Unauthorized | 请求要求用户的身份认证 |
| 403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
| 404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
| 405 | Method Not Allowed | 客户端请求中的方法被禁止 |
-
http header
- Cache-Control
简单理解,强缓存
- Expires
Expires指定的时间根据服务器配置可能有两种:
1. 文件最后访问时间
2. 文件绝对修改时间
如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖
- max-age(相对请求时间)
web中的文件被用户访问(请求)后的存活时间
- last-modified
WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间
- ETag
对象(比如URL)的标志值 ,文件被修改,Etag也会修改
- If-Modified-Since
请求值 , 由客户端发送给服务端上次返回的资源修改时间
总结
实际操作过程中用户行为主要会触发3种缓存策略:
- 打开网页,地址栏输入地址: 查找
disk cache中是否有匹配。如有则使用;如没有则发送网络请求。
- 普通刷新 (F5):因为 TAB 并没有关闭,因此
memory cache是可用的,会被优先使用(如果匹配的话)。其次才是disk cache。会跳过强缓存,进行协商缓存判断。
- 强制刷新 (Ctrl + F5):浏览器不使用缓存,跳过协商缓存和强缓存,直接从服务器拉取,,服务器返回 200 和最新内容。
1.频繁变动的资源
Cache-Control: no-cache
对于频繁变动的资源,首先需要使用
Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。2.不常变化的资源
Cache-Control: max-age=31536000
通常在处理这类资源时,给它们的 Cache-Control 配置一个很大的
max-age=31536000 (一年),这样浏览器之后请求相同的 URL 会命中强制缓存。而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符在线提供的类库 (如
jquery/2.0.2/jquery-2.0.2.min.js)所以实际应用中,遇到资源更新之后,还是有缓存的情况,除了刷新cdn,还要检查下是否有设置http响应头,做对应的缓存过期时间处理。如果没有做缓存过期策略,并且走了 disk cache,可能怎么刷新都没办法获取最新的资源。

浙公网安备 33010602011771号