浅谈浏览器存储

浅谈浏览器存储

1、概念

浏览器存储 :浏览器存储是指浏览器提供的一种本地存储数据的机制,包括:CookieWeb StorageIndexedDB 等。

前端持久化存储 :是指通过 JavaScript 在客户端进行数据持久化存储的方式,包括 LocalStorageIndexedDBFile API 等。

表格一览

特性 cookie localStorage sessionStorage indexDB
数据生命周期 一般由服务器生成,可以设置过期时间;前端采用和js-cookie等组件也可以生成 除非被清理,否则一直存在;浏览器关闭还会保存在本地,但是不支持跨浏览器 页面关闭就清理刷新依然存在,不支持跨页面交互 除非被清理,否则一直存在
数据存储大小 4K 5M 5M 不限制大小
与服务端通信 每次都会携带在请求的header 中,对于请求性能有影响;同时由于请求中都带有,所以也容易出现安全问题 不参与 不参与 不参与
特点 字符串键值对在本地存储数据 字符串键值对在本地存储数据 字符串键值对在本地存储数据 IndexedDB 是一个非关系型数据库(不支持通过 SQL 语句操作)。可以存储大量数据,提供接口来查询,还可以建立索引,这些都是其他存储方案无法提供的能力。

2、Cookie

Cookie 最开始被设计出来其实并不是来做本地存储的,而是为了弥补HTTP状态管理上的不足

HTTP 协议是一个无状态协议,客户端向服务器发请求,服务器返回响应,故事就这样结束了,但是下次发请求如何让服务端知道客户端是谁呢?

这种背景下,就产生了 Cookie.

Cookie 本质上就是浏览器里面存储的一个很小的文本文件,内部以键值对的方式来存储(在chrome开发者面板的Application这一栏可以看到)。向同一个域名下发送请求,都会携带相同的 Cookie,服务器拿到 Cookie 进行解析,便能拿到客户端的状态。它可以设置过期时间,用于在客户端和服务器之间传递数据。由于每次请求都会携带 Cookie 信息,可能导致网络开销增加,并且存在安全性问题,故不适合存储大量数据。

Cookie过期等配置

Cookie 分为:Session Cookie 和持久型 CookieCookie 设置中有个 HttpOnly 参数,前端浏览器使用document.cookie 是读取不到 HttpOnly 类型的 Cookie 的,被设置为 HttpOnlyCookie 记录只能通过 HTTP 请求头发送到服务器端进行读写操作,这样就避免了服务器的 Cookie 记录被前端 javascript 修改,保证了服务器验证 Cookie 的安全性。

Cookie 的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成 Cookie 的作用范围。若不设置过期时间,则表示这个 Cookie 的生命期为浏览器会话期间,关闭浏览器窗口, Cookie 就消失。

这种生命期为浏览器会话期的 Cookie 被称为 会话Cookie会话Cookie 一般不存储在硬盘上而是保存在内存里。若设置了过期时间,浏览器就会把 Cookie 保存到硬盘上,关闭后再次打开浏览器,这些 Cookie 仍然有效直到超过设定的过期时间。存储在硬盘上的 Cookie 可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的 Cookie ,不同的浏览器有不同的处理方式。

操作方式

js 复制代码
// 设置Cookie:
function setCookie(name, value, days) {
  let expires = "";
  if (days) {
    const date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    expires = "; expires=" + date.toUTCString();
  }
  document.cookie = name + "=" + value + expires + "; path=/";
}


// 读取Cookie
function getCookie(name) {
  const nameEQ = name + "=";
  const ca = document.cookie.split(';');
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) === ' ') {
      c = c.substring(1, c.length);
    }
    if (c.indexOf(nameEQ) === 0) {
      return c.substring(nameEQ.length, c.length);
    }
  }
  return null;
}

// 删除Cookie
function deleteCookie(name) {
  setCookie(name, "", -1);
}

// 使用
// 设置Cookie,有效期为7天
setCookie("username", "john_doe", 7);
console.log(cookie); // "username=john_doe; expires=Fri, 04 Aug 2023 14:47:16 GMT; path=/"

// 读取Cookie
const username = getCookie("username");
console.log(username); // "john_doe"

// 删除Cookie
deleteCookie("username");

Cookie 的作用很好理解,就是用来做状态存储的,但它也是有诸多致命的缺陷的:

  • 容量缺陷。Cookie 的体积上限只有4KB,只能用来存储少量的信息。
  • 性能缺陷。Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ,请求都会携带上完整的 Cookie,这样随着请求数的增多,其实会造成巨大的性能浪费的,因为请求携带了很多不必要的内容。
  • 安全缺陷。由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获,然后进行一系列的篡改,在 Cookie 的有效期内重新发送给服务器,这是相当危险的。另外,在HttpOnlyfalse 的情况下,Cookie 信息能直接通过 JS 脚本来读取。

3、Session

session 机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程序需要为某个客户端的请求创建一个session 时,服务器首先检查这个客户端的请求里是否已包含了一个session 标识(称为 session ID),如果已包含则说明以前已经为此客户端创建过 session,服务器就按照 session ID 把这个session 检索出来使用(检索不到,会新建一个),如果客户端请求不包含 session ID,则为此客户端创建一个session 并且生成一个与此session 相关联的 session IDsession ID 的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session ID 将被在本次响应中返回给客户端保存。

总结

  • 服务器端存储session 是服务器端的一种机制,用于在服务端存储用户会话数据。服务器会为每个用户创建一个唯一的 session,并在客户端保存一个对应的 session ID
  • 生命周期session 的生命周期由服务器管理,可以设置 session 的过期时间,当用户长时间不活动或超过过期时间时,session 会被销毁。

Cookie 和 Session 比较

  • cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
  • cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗
  • session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
  • 单个 cookie 保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个 cookie
  • 个人建议:将登录信息等重要信息存放在 session 中,其他信息如果需要在每个请求中携带,可以放在 cookie 中,剩下的信息本地化缓在 Web Storage 中。

4、Web Storage

Web Storage 包括 localStoragesessionStorage,是 HTML5 新增的浏览器存储机制。它们在浏览器端存储数据,不会随着每次请求发送到服务器,所以不会增加网络开销。localStorage 存储的数据没有过期时间,除非用户手动清除或网站清除,否则数据会一直存在。sessionStorage 的数据在用户关闭浏览器或页面后会被清除,适用于临时性数据存储。

4.1、localStorage

localStorage 有一点跟 Cookie 一样,就是针对一个域名,即在同一个域名下,会存储相同的一段。它可以存储较大量的数据,数据不会过期,一直保留在客户端。由于数据保存在客户端,所以不会增加服务器负担。单个 localStorage 的大小受限,可以用多个 iframe 方式使用多个域名来突破单个页面下 localStorage 存储数据的最大限制。

特别说明:浏览器多个标签页打开同个域名时,localStorage 内容一般是共享的。其位置这可以监听事件 storage 来做一致性操作响应处理。这样会导致如下现象:

标签页一:通过某行为修改 localStorage 中某个属性值,然后数据接口依赖该属性值;

标签页二:由于 localStorage 标签页间共享,导致标签页二数据不准确!

操作方式

接下来我们来具体看看如何来操作 localStorage

js 复制代码
let obj = { name: "sanyuan", age: 18 };

localStorage.setItem("name", "sanyuan"); 
localStorage.setItem("info", JSON.stringify(obj));

接着进入相同的域名时就能拿到相应的值:

js 复制代码
let name = localStorage.getItem("name"); 
let info = JSON.parse(localStorage.getItem("info"));

从这里可以看出,localStorage 其实存储的都是字符串,如果是存储对象需要调用 JSON.stringify 方法,并且用 JSON.parse 来解析成对象。

应用场景

利用 localStorage 的较大容量和持久特性,可以利用 localStorage 存储一些内容稳定的资源,比如官网的 logo,或者存储 Base64 格式的图片资源等。

Cookie 和 localStorage 比较

  • localStorage 的容量上限为 5M,相比于Cookie4K 大大增加。当然这个 5M 是针对一个域名的,因此对于一个域名是持久存储的。
  • 只存在客户端,默认不参与与服务端的通信。这样就很好地避免了 Cookie 带来的性能问题安全问题
  • 接口封装。通过 localStorage 暴露在全局,并通过它的 setItemgetItem 等方法进行操作,非常方便。

4.2、sessionStorage

sessionStoragelocalStoragecookie 都是在浏览器端存储的数据,其中 sessionStorage 的概念很特别,引入了一个"浏览器窗口"的概念。sessionStorage 是在同源的同窗口(或tab)中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage 即被销毁。同时"独立"打开的不同窗口,即使是同一页面,sessionStorage 对象也是不同的。

临时存储

很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用 sessionStorage 非常方便。

sessionStorage 以下方面和 localStorage 一致:

  • 容量。容量上限也为 5M。
  • 只存在客户端,默认不参与与服务端的通信。
  • 接口封装。除了sessionStorage名字有所变化,存储方式、操作方式均和localStorage一样。

sessionStoragelocalStorage 有一个本质的区别,那就是前者只是 会话级别的存储 ,并不是 持久化存储 。会话结束,也就是页面关闭,这部分 sessionStorage 就不复存在了。

操作方式

接下来我们来具体看看如何来操作 sessionStorage

js 复制代码
//存储
sessionStorage.setItem("name", "sanyuan"); 

//取出
sessionStorage.getItem("name");

//清除 
sessionStroage.clear();

应用场景

  • 可以用它对表单信息进行维护,将表单信息存储在里面,可以保证页面即使刷新也不会让之前的表单信息丢失。
  • 可以用它存储本次浏览记录。如果关闭页面后不需要这些记录,用 sessionStorage 就再合适不过了。事实上微博就采取了这样的存储方式。

5、IndexedDB

IndexedDB 是运行在浏览器中的非关系型数据库,为大型数据的存储提供了接口。 本质上是数据库,绝不是和刚才 WebStorage5M 一个量级,理论上这个容量是没有上限的。

关于它的使用,本文侧重原理,而且 MDN 上的教程文档已经非常详尽,这里就不做赘述了,感兴趣可以看一下使用文档

IndexedDB的存储空间(所有访问的网站总和)为磁盘可用空间的50%,或根据浏览器的设定分配;

接着我们来分析一下 IndexedDB 的一些重要特性,除了拥有数据库本身的特性,比如支持事务存储二进制数据,还有这样一些特性需要格外注意:

  • 键值对存储。内部采用对象仓库存放数据,在这个对象仓库中数据采用键值对的方式来存储。
  • 异步操作。数据库的读写属于 I/O 操作, 浏览器中对异步 I/O 提供了支持。
  • 受同源策略限制,即无法访问跨域的数据库。
  • 它是 NoSQL 的,不需要我们去写一些特定的 SQL 语句来对数据库进行操作,数据形式使用的 json
  • 一个数据库中可以包含多种对象集合,相对于 SQL 数据库来说就是多个表;在一个域(名)下,还可以有多个数据库。但是不能跨域访问别的域名之下的数据库。

另外一方面,用 localStorage 只能保存字符串,如果是其他的类型,那就必须用 JSON.stringify 来转换为字符串后再保存,而 IndexedDB 则可以直接保存。此外,还具备一般 DBMS 的常用功能,例如遍历、筛选等。

indexedDB出现的意义

  • 前端存储,已经有了 localStorageCookies ,但是它们都是比较简单的技术。而 IndexedDB 提供了类似数据库风格的数据储存和使用方式。
  • Cookies 只能是字符串,储存空间有限,每次 HTTP 接受和发送都会传递 Cookies 数据,它会占用额外的流量。
  • localStorage 是用 key-value 键值模式储存数据,想让 localstorage 存储对象,你需要借助 JSON.stringify() 能将对象变成字符串形式,再用 JSON.parse() 将字符串还原成对象,当存储的数据庞大时,这就不是最佳的方案了,localstorage 就是专门为小数量数据设计的,它的 api 设计为同步的。
  • IndexedDB 很适合存储大量数据,它的 API 是异步调用的,IndexedDB 使用索引存储数据,各种数据库操作放在事务中执行,IndexedDB 支持简单的数据类型,它比 localstorage 强大,API 也相对复杂,对于简单的数据,还是使用 localstorage
  • IndexedDB 能提供更为复杂的查询数据的方式。

IndexedDB特点

  • 非关系型数据库(NoSql) :我们都知道 MySQL 等数据库都是关系型数据库,它们的主要特点就是数据都以一张二维表的形式存储,而 IndexedDB 是非关系型数据库,主要以键值对的形式存储数据。
  • 持久化存储cookielocalStoragesessionStorage 等方式存储的数据当我们清楚浏览器缓存后,这些数据都会被清除掉的,而使用 IndexedDB 存储的数据则不会,除非手动删除该数据库。
  • 异步操作IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他的操作,这与 localstorage 形成鲜明的对比,后者是同步的。
  • 支持事务IndexedDB 支持事务(transaction),这意味着一系列的操作步骤之中,只要有一步失败了,整个事务都会取消,数据库回滚的事务发生之前的状态,这和 MySQL 等数据库的事务类似。
  • 同源策略IndexedDB 同样存在同源限制,每个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  • 存储容量大 :这也是 IndexedDB 最显著的特点之一了,这也是不用 localStorage 等存储方式的最好理由。

操作方式

js 复制代码
/**
 * 打开数据库
 * @param {object} dbName 数据库的名字
 * @param {string} storeName 仓库名称
 * @param {string} version 数据库的版本
 * @return {object} 该函数会返回一个数据库实例
 */
function openDB(dbName, version = 1) {
  return new Promise((resolve, reject) => {
    //  兼容浏览器
    var indexedDB =
      window.indexedDB ||
      window.mozIndexedDB ||
      window.webkitIndexedDB ||
      window.msIndexedDB;
    let db;
    // 打开数据库,若没有则会创建
    const request = indexedDB.open(dbName, version);
    // 数据库打开成功回调
    request.onsuccess = function (event) {
      db = event.target.result; // 数据库对象
      console.log("数据库打开成功");
      resolve(db);
    };
    // 数据库打开失败的回调
    request.onerror = function (event) {
      console.log("数据库打开报错");
    };
    // 数据库有更新时候的回调
    request.onupgradeneeded = function (event) {
      // 数据库创建或升级的时候会触发
      console.log("onupgradeneeded");
      db = event.target.result; // 数据库对象
      var objectStore;
      // 创建存储库
      objectStore = db.createObjectStore("signalChat", {
        keyPath: "sequenceId", // 这是主键
        // autoIncrement: true // 实现自增
      });
      // 创建索引,在后面查询数据的时候可以根据索引查
      objectStore.createIndex("link", "link", { unique: false }); 
      objectStore.createIndex("sequenceId", "sequenceId", { unique: false });
      objectStore.createIndex("messageType", "messageType", {
        unique: false,
      });
    };
  });
}
......

我们将创建数据库的操作封装成了一个函数,并且该函数返回一个 promise 对象,使得在调用的时候可以链式调用,函数主要接收两个参数:数据库名称、数据库版本。函数内部主要有三个回调函数,分别是:

  • onsuccess:数据库打开成功或者创建成功后的回调,这里我们将数据库实例返回了出去。
  • onerror:数据库打开或创建失败后的回调。
  • onupgradeneeded:当数据库版本有变化的时候会执行该函数,比如我们想创建新的存储库(表),就可以在该函数里面操作,更新数据库版本即可。

应用场景

  • IndexedDB 是异步操作的,适合存储大量数据或需要离线访问的应用。
  • 数据可视化等界面,大量数据,每次请求会消耗很大性能。
  • 即时聊天工具,大量消息需要存在本地。
  • 其它存储方式容量不满足时,不得已使用 IndexedDB

6、其他存储

  • WebSQL:二维表的形成存储大量数据到客户端,但目前只有 Chrome 浏览器有。
  • Application Cache:通过 manifest 配置文件在本地有选择性地存储 javascriptcss、图片等静态资源文件的文件缓存机制,已废弃。
  • cacheStorage:在 ServiceWorker 规范中定义的,用于保存每个 ServiceWorker声明的 Cache 对象,未来可能替代 Application Cache 的离线方案。
  • Flash缓存:主要基于 Flash,具有读写浏览器本地目录的功能。
  • File APIFile API 允许前端通过 JavaScript 读取和操作用户的本地文件。可以实现将文件存储在客户端,并在需要时读取和处理文件数据。

7、区别

  1. localStorage
  • 存储容量较大localStorage 可以存储较大量的数据,通常可以存储 5MB 的数据。
  • 持久性localStorage 中的数据不会过期,除非用户手动清除或网站清除,否则数据会一直保留在客户端。
  • 作用域localStorage 的作用域是整个域名,即在同一个域名下的所有页面都可以访问同一份 localStorage 数据。
  1. sessionStorage
  • 存储容量较大 :与 localStorage 一样,通常可以存储 5MB 的数据。
  • 会话级别sessionStorage 中的数据在当前会话期间有效,即在用户关闭当前浏览器窗口或标签页后,数据会被清除。
  • 作用域sessionStorage 的作用域是当前窗口或标签页,不同窗口或标签页之间无法共享数据。
  1. session
  • 服务器端存储session 是服务器端的一种机制,用于在服务端存储用户会话数据。服务器会为每个用户创建一个唯一的 session,并在客户端保存一个对应的 session ID
  • 生命周期session 的生命周期由服务器管理,可以设置 session 的过期时间,当用户长时间不活动或超过过期时间时, session 会被销毁。
  1. cookies
  • 存储容量小cookies 的存储容量较小,一般限制在 4KB 左右。
  • 持久性 :可以设置 cookies 的过期时间,可以是会话级的,也可以是持久性的。当设置了过期时间,cookies 会在过期后被删除。
  • 作用域cookies 的作用域是整个域名,与 localStorage 类似,在同一个域名下的所有页面都可以访问相同的 cookies 数据。
  1. IndexedDB
  • 存储容量大IndexedDB 是一种数据库,可以存储较大量的结构化数据,一般可以存储几十MB甚至几百MB的数据。
  • 异步操作IndexedDB 是异步的,操作数据时需要使用异步API 进行处理。
  • 丰富的查询功能IndexedDB 支持复杂的数据查询和索引,可以高效地检索和处理大量数据。

8、总结

  • localStoragesessionStorageHTML5 新增的浏览器存储机制,用于在客户端存储数据。
  • session 是服务器端的存储机制,用于在服务端存储用户会话数据。
  • cookies 是在客户端和服务端都可以操作的存储机制,用于存储少量数据。它可以设置过期时间,可以用于跟踪用户状态和实现记住登录功能。
  • localStoragesessionStoragesessioncookies 是浏览器端的存储机制,用于在客户端存储数据,容量和持久性各有不同。
  • IndexedDB 是一种高级的浏览器端数据库,适用于需要存储大量结构化数据并进行复杂查询的场景。它与其他浏览器存储方式相比,存储容量更大且查询效率更高,但使用起来相对复杂一些,需要异步操作。
相关推荐
亿牛云爬虫专家11 天前
使用Selenium与WebDriver实现跨浏览器自动化数据抓取
python·selenium·自动化·浏览器·爬虫代理·webdriver·代理ip
日升_rs15 天前
JavaScript 中 structuredClone 和 JSON.parse(JSON.stringify()) 克隆对象的区别
javascript·浏览器·es 新特性
日升_rs16 天前
Chrome 浏览器插件获取网页 window 对象(方案三)
chrome·浏览器·chrome 浏览器插件
楚门边境23 天前
收藏夹里的“小网站”被误报违规不让上怎么办?如何将Chrome和Edge安装到 D 盘(含用户数据),重装系统也不会丢失收藏夹和密码?
chrome·edge·浏览器
SunkingYang1 个月前
谷歌chrome浏览器显示“版本太旧”又无法更新情况下,如何关闭“Chrome版本太旧”提示,包括直接启动Google浏览器,或者通过其他应用启动
chrome·浏览器·google浏览器·版本太久·关闭版本太久提示·chrome版本太久·关闭提示
dralexsanderl1 个月前
fetch 在实际项目中的思考
javascript·浏览器
最小生成树1 个月前
Cookie、localStorage 和 sessionStorage 的区别及应用实例
浏览器
如意呀1 个月前
深入理解两种数据拦截方式的区别
javascript·vue.js·浏览器
GuokLiu2 个月前
240803-沉侵式翻译插件配置Ollama的API实现网页及PDF文档的翻译
pdf·浏览器·插件·翻译·ollama·沉侵式翻译
李不言2 个月前
巧妙解决浏览器插件中的跨域问题:一个实用方案
前端·浏览器