浏览器存储技术


作者:Seiya

时间:2019年09月02日


前言


随着移动网络的发展与演化,我们手机上现在除了有原生 App,还能跑“WebApp”——它即开即用,用完即走。一个优秀的 WebApp 甚至可以拥有和原生 App 媲美的功能和体验。WebApp 优异的性能表现,有一部分原因要归功于浏览器存储技术的提升。cookie 存储数据的功能已经很难满足开发所需,逐渐被 WebStorage、IndexedDB 所取代。






Cookie 指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。 cookie是服务端生成,客户端进行维护和存储。

通过cookie,可以让服务器知道请求是来源哪个客户端,就可以进行客户端状态的维护,比如登陆后刷新,请求头就会携带登陆时response header中的 set-cookie,Web 服务器接到请求时也能读出 cookie 的值,根据 cookie 值的内容就可以判断和恢复一些用户的信息状态。



  • Cookie 不够大

    Cookie的大小限制在4KB左右,对于复杂的存储需求来说是不够用的。当 Cookie 超过 4KB 时,它将面临被裁切的命运。这样看来,Cookie 只能用来存取少量的信息。此外很多浏览器对一个站点的cookie个数也是有限制的。

  • 过多的 Cookie 会带来巨大的性能浪费

    Cookie 是紧跟域名的。同一个域名下的所有请求,都会携带 Cookie。大家试想,如果我们此刻仅仅是请求一张图片或者一个 CSS 文件,我们也要携带一个 Cookie 跑来跑去(关键是 Cookie 里存储的信息并不需要),这是一件多么劳民伤财的事情。Cookie 虽然小,请求却可以有很多,随着请求的叠加,这样的不必要的 Cookie 带来的开销将是无法想象的。

    cookie是用来维护用户信息的,而域名(domain)下所有请求都会携带cookie,但对于静态文件的请求,携带cookie信息根本没有用,此时可以通过cdn(存储静态文件的)的域名和主站的域名分开来解决。

  • 由于在 HTTP 请求中的 Cookie 是明文传递的,所以安全性成问题,除非用 HTTPS





LocalStorage


为了弥补 Cookie 的局限性,让“专业的人做专业的事情”,Web Storage 出现了。HTML5 中新增了本地存储的解决方案----Web Storage,它分成两类:sessionStorage和localStorage。这样有了 WebStorage 后,cookie 能只做它应该做的事情了——作为客户端与服务器交互的通道,保持客户端状态。



LocalStorage 的特点

  • 保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前保存的数据。

  • 大小为5M左右

  • 仅在客户端使用,不和服务端进行通信

  • 接口封装较好

基于上面的特点,LocalStorage可以作为浏览器本地缓存方案,用来提升网页首屏渲染速度(根据第一请求返回时,将一些不变信息直接存储在本地)。



存入/读取数据

localStorage保存的数据,以“键值对”的形式存在。也就是说,每一项数据都有一个键名和对应的值。所有的数据都是以文本格式保存。存入数据使用setItem方法。

<script>
if(window.localStorage){
  localStorage.setItem('name','world')
  localStorage.setItem('gender','female'}
</script>


使用场景

LocalStorage在存储方面没有什么特别的限制,理论上 Cookie 无法胜任的、可以用简单的键值对来存取的数据存储任务,都可以交给 LocalStorage 来做。比如:考虑到 LocalStorage 的特点之一是持久,有时我们更倾向于用它来存储一些内容稳定的资源。比如图片内容丰富的电商网站会用它来存储 Base64 格式的图片字符串:





sessionStorage


sessionStorage 保存的数据用于浏览器的一次会话,当会话结束(通常是该窗口关闭),数据被清空。

sessionStorage 特别的一点在于,即便是相同域名下的两个页面,只要它们不在同一个浏览器窗口中打开,那么它们的 sessionStorage 内容便无法共享;localStorage 在所有同源窗口中都是共享的;cookie 也是在所有同源窗口中都是共享的,除了保存期限的长短不同。



sessionStorage 的特点

  • 会话级别的浏览器存储

  • 大小为5M左右

  • 仅在客户端使用,不和服务端进行通信

  • 接口封装较好

基于上面的特点,sessionStorage 可以有效对表单信息进行维护,比如刷新时,表单信息不丢失。



使用场景

sessionStorage 更适合用来存储生命周期和它同步的会话级别的信息。这些信息只适用于当前会话,当你开启新的会话时,它也需要相应的更新或释放。比如微博的 sessionStorage就主要是存储你本次会话的浏览足迹。






  • 共同点:都是保存在浏览器端,且都遵循同源策略。

  • 不同点:在于生命周期与作用域的不同

    • 作用域:

      localStorage 只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份 localStorage 数据。sessionStorage 比localStorage 更严苛一点,除了协议、主机名、端口外,还要求在同一窗口(也就是浏览器的标签页)下;

    • 生命周期:

      localStorage 是持久化的本地存储,存储在其中的数据是永远不会过期的,使其消失的唯一办法是手动删除;而 sessionStorage 是临时性的本地存储,它是会话级别的存储,当会话结束(页面被关闭)时,存储内容也随之被释放。


说到底,Web Storage 是对 Cookie 的拓展,它只能用于存储少量的简单数据。当遇到大规模的、结构复杂的数据时,Web Storage 也爱莫能助了。这时候我们就要清楚我们的终极大 boss——IndexedDB!





IndexedDB


IndexedDB 是一种低级API,用于客户端存储大量结构化数据(包括文件和blobs)。该API使用索引来实现对该数据的高性能搜索。IndexedDB 是一个运行在浏览器上的非关系型数据库。既然是数据库了,那就不是 5M、10M 这样小打小闹级别了。理论上来说,IndexedDB 是没有存储上限的(一般来说不会小于 250M)。它不仅可以存储字符串,还可以存储二进制数据。



IndexedDB 的特点

  • 键值对储存

    IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。

  • 异步

    IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

  • 支持事务

    IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

  • 同源限制

    IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

  • 储存空间大

    IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。

  • 支持二进制储存

    IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。



IndexedDB 的常见操作

  • 建立打开IndexedDB ---- window.indexedDB.open("testDB")

    这条指令并不会返回一个DB对象的句柄,我们得到的是一个IDBOpenDBRequest对象,而我们希望得到的DB对象在其result属性中


    除了 result,IDBOpenDBRequest 接口定义了几个重要属性:
    • onerror:请求失败的回调函数句柄

    • onsuccess:请求成功的回调函数句柄

    • onupgradeneeded:请求数据库版本变化句柄

  • 关闭IndexedDB ---- indexdb.close()

  • 删除IndexedDB ---- window.indexedDB.deleteDatabase(indexdb)





总结


  • Cookie 的本职工作并非本地存储,而是“维持状态”;

  • Web Storage 是 HTML5 专门为浏览器存储而提供的数据存储机制,不与服务端发生通信;

  • IndexedDB 用于客户端存储大量结构化数据;

最后更新时间: 2019-9-2 18:07:36