cookie 最初设计并不是用来做本地存储的,而是用来弥补 HTTP 状态管理上的不足。
HTTP 协议是一个无状态协议,客户端向服务器发请求,服务器返回响应。在连接关闭后,服务端不会记录用户的信息,而 cookie 的作用就是用于解决“如何记录客户端的用户信息”。
cookie 本质上就是浏览器里面存储的一个很小的文本文件,内部以键值对的方式来存储。向同一域名下发送请求,都会携带相同的 cookie,服务器拿到 cookie 进行解析,便能拿到客户端的状态。
cookie 的作用是做状态存储,但它也是有诸多致命的缺陷的:
- 容量缺陷:cookie 的体积上限只有
4KB
,只能用来存储少量的信息。 - 性能缺陷:cookie 紧跟域名,同一个域名下的所有请求,都会携带 cookie(可以通过存储静态文件的CDN的域名和主站的域名分开来解决)。随着请求数的增多,会造成性能的浪费,因为请求携带了很多不必要的内容。
- 安全缺陷:由于 cookie 以纯文本明文的形式在浏览器和服务器中传递,很容易被非法用户截获,然后进行一系列的篡改,在 cookie 的有效期内重新发送给服务器。另外,在
HttpOnly
为 false 的情况下,cookie 信息能直接通过 JS 脚本来读取。
localStorage 有一点跟 cookie 一样,就是针对一个域名,即在同一个域名下,会存储相同的一段 localStorage。
与 cookie 的区别:
- 容量。localStorage 的容量上限为 5M,相比于 cookie 的 4K 大大增加。当然这个 5M 是针对一个域名的,因此对于一个域名是持久存储的。
- 只存在客户端,默认不参与与服务端的通信。这样就很好地避免了 cookie 带来的性能问题和安全问题。
- 接口封装。通过
localStorage
暴露在全局,并通过它的setItem
和getItem
等方法进行操作,非常方便。
利用 localStorage
的较大容量和持久特性,可以利用 localStorage
存储一些内容稳定的资源,比如官网的 logo,存储 Base64 格式的图片资源
sessionStorage
以下方面和 localStorage
一致:
- 容量。容量上限也为 5M。
- 只存在客户端,默认不参与与服务端的通信。
- 接口封装。除了
sessionStorage
名字有所变化,存储方式、操作方式均和localStorage
一样。
但 sessionStorage
和 localStorage
有一个本质的区别,那就是前者只是会话级别的存储,并不是持久化存储。会话结束,也就是页面关闭,这部分sessionStorage
就不复存在了。
- 可以用它对表单信息进行维护,将表单信息存储在里面,可以保证页面即使刷新也不会让之前的表单信息丢失。
- 可以用它存储本次浏览记录。如果关闭页面后不需要这些记录,用
sessionStorage
就再合适不过了。
- 都是保存在浏览器端,且都是字符串类型的键值对。
- 都遵循同源策略
-
传递方式不同
- cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器间来回传递。
- sessionStorage 和 loaclStorage 不会自动把数据发给服务器,仅在本地保存。
-
数据大小不同
- cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下。存储大小限制也不同,cookie 数据不能超过 4KB,同时因为每次 http 请求都会携带 cookie,所以 cookie 只适合保存很小的数据,如会话标识。
- sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到 5M 或者更大。
-
数据有效期不同
- cookie:只在设置 cookie 过期时间之前一直有效,即使窗口或浏览器关闭;
- localStorage:始终有效,窗口或浏览器关闭也一直保存,除非手动删除,因此用作持久数据;
- sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持。
-
作用域不同
- cookie:在所有同源窗口中都是共享的;
- localStorage:在所有同源窗口中也都是共享的;
- sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面。
IndexedDB 是运行在浏览器中的非关系型数据库, 本质上是数据库,绝不是和刚才 WebStorage 的 5M 一个量级,理论上这个容量是没有上限的。
IndexedDB 除了拥有数据库本身的特性,比如支持事务,存储二进制数据,还有一些特性需要格外注意:
- 键值对存储。内部采用对象仓库存放数据,在这个对象仓库中数据采用键值对的方式来存储。
- 异步操作。数据库的读写属于 I/O 操作, 浏览器中对异步 I/O 提供了支持。
- 受同源策略限制,即无法访问跨域的数据库。
浏览器中各种本地存储和缓存技术的发展,给前端应用带来了大量的机会,PWA 也正是依托了这些优秀的存储方案才得以发展起来。重新梳理一下这些本地存储方案:
- cookie 并不适合存储,而且存在非常多的缺陷。
- Web Storage 包括 localStorage 和 sessionStorage, 默认不会参与和服务器的通信。
- IndexedDB 为运行在浏览器上的非关系型数据库,为大型数据的存储提供了接口。