浏览器缓存

技术 4月 20, 2021

构成此刻我们的是过去,过去转换成大脑里的记忆
浏览器也存在它自己的 memory

HTTP Cookie

概述

HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。

Cookie 曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。由于服务器指定 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器API已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB

特性

  • 创建方式:可以由服务端通过 HTTP Response Header 中的 Set-Cookie 主动创建,也可以由客户端通过 document.cookie 修改创建。
  • 个数限制:根据不同浏览器限制个数不同,每个域少则 20 个,多则 50 多个
  • 大小限制:大部分浏览器都控制在 4KB 左右的大小
  • 生命周期控制
    • 会话期 cookie:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效
      • 不设置 Max-Age 或者 Expires 便是会话期 cookie
      • 有些浏览器并不会严格遵循会话结束便删除会话期 cookie 的规矩,可能会适当保留会话期 cookie
    • 持久性 cookie:根据 Max-Age 或者 Expires 在浏览器中主动存在多久
      • Max-Age 优先级高于 Expires
  • 访问限制
    • Secure:标记为 Secure 的 cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,可以防止 中间者攻击(MitM),但实际上 cookie 始终是不安全的,攻击者可以从硬盘中获取 cookie 内容
    • HttpOnly:标记为 HttpOnly 的 cookie 就不能通过 document.cookie 来访问,可以有助于防止 跨站点脚本攻击(XSS)
  • 作用域限制
    • DomainDomain 指定了哪些主机可以接受 Cookie,默认只有同源的可以使用,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如developer.mozilla.org)
    • PathPath 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。
    • SameSite:Cookie 允许服务器要求某个 cookie 在跨站请求时不会被发送,(其中 Site 由可注册域定义),从而可以阻止 跨站请求伪造攻击(CSRF)
      • None:浏览器会在同站请求、跨站请求下继续发送 cookies,不区分大小写
      • Strict:浏览器将只在访问相同站点时发送 cookie。(在原有 Cookies 的限制条件上的加强,如上文 “Cookie 的作用域” 所述)
      • Lax:与 Strict 类似,但用户从外部站点导航至URL时(例如通过链接)除外。 在新版本浏览器中,为默认选项,Same-site cookies 将会为一些跨站子请求保留,如图片加载或者frames 的调用,但只有当用户从外部站点导航到URL时才会发送。如 link 链接
  • 通过控制前缀来反向要求 cookie 的属性
    • __Host-:如果 cookie 名称具有此前缀,则仅当它也用 Secure 属性标记,是从安全来源发送的,不包括 Domain 属性,并将 Path 属性设置为 / 时,它才在 Set-Cookie 标头中接受。这样,这些 cookie 可以被视为 “domain-locked”。
    • __Secure-:如果 cookie 名称具有此前缀,则仅当它也用 Secure 属性标记,是从安全来源发送的,它才在 Set-Cookie 标头中接受。该前缀限制要弱于 __Host- 前缀。

优势

由于是浏览器早期便存在的特性,所以兼容性极好,可以兼容几乎所有主流浏览器。

劣势

  • 存储量小,大部分浏览器都支持只支持 4KB 的存储大小
  • 安全性低,可能被篡改、拦截。拦截后很容易获取所有的 session 信息
  • 性能较差,在没有特定约束下,请求可能会携带大量 cookie,导致无意义的性能浪费
  • 容易被用户限制,用户可以轻易的关闭 cookie 功能,从而导致部分功能的缺失

Web storage API

概述

严格意义上来说 Cookie 并非专门为存储而准备的,从 cookie 的名字上就可以知道,只是用于提供给服务器一些小线索来确定当前用户状态的
而 Web storage API 可以说在 cookie 的基础上加强了存储的概念,脱离了与服务器的关系,同时提供了更大的存储空间,可以让用户存储更多信息,提供给了开发者更好的 API 去 存储/获取 已键值对存放的数据。

Web storage API 划分出了两个机制,一种叫 sessionStorage,另一种叫 localStorage,两者在接口 API,存储大小上没有差异,唯一有差异的地方就是生命周期

sessionStorage

sessionStorage 适用于存储生命周期与页面会话几乎同步的信息。
比如说用户的浏览足迹,该信息仅在当前会话有意义,每次会话都需要得到释放。

特性

  • 会话级别的浏览器存储
  • 大小为 5MB 左右
  • 仅在客户端使用,不和服务端进行通信
  • 接口封装的好
  • 支持变化监听

注意

sessionStorage 对于会话的生命周期有些特别,也较为敏感,若不知晓可能会造成与开发意图不统一的问题
cookie 对会话的生命周期较为简单粗暴,可以理解为本次浏览器启动期间同一个源的页面,都在一个会话中,会话只在浏览器关闭后结束
而 sessionStorage,并非如此,只有当前页面和由当前页面打开的同源页面存在期间内,才算一个完整的对话。所以即便是同源页面,如果都是单独打开的,则都不算同一个会话。如果一个页面及由他打开的页面关闭了,则视为会话结束

localStorage

localStorage 适用于长于会话的数据的存储。
比如说页面主题的设置,可能需要在多次访问页面的时候都能帮助页面渲染预设好的主题。

特性

  • 长持久的浏览器存储
  • 大小为 5MB 左右
  • 仅在客户端使用,不和服务端进行通信
  • 接口封装的好
  • 支持变化监听

优势

  • 兼容性较好
  • 较好的安全性,不会涉及与服务端请求
  • 较大的空间,存储轻量级的数据绰绰有余
  • 较好的 API
  • 支持变化监听

劣势

  • 没有优雅可控的生命周期管理机制,sessionStorage 对于会话的定义有时略显鸡肋,localStorage 需要主动控制数据的有效期
  • 存储的 value 只能是字符串,对于复杂的数据只能通过 JSON.stringify 转义后存储
  • 监听只能在,另一个页面触发数据变动时才能响应,当前页面触发的数据变动无法响应

IndexedDB API

概述

在大部分时候,客户端页面只需要存储一些轻量简单的数据就能带来相当好的用户体验,Web storage API 完全可以胜任,而当我们需要存储大型复杂的数据的时候,Web storage API 就显的促膝见肘了,既不支持大型数据,也不支持复杂数据类型的数据。

IndexedDB 是一个事务型数据库系统,类似于基于 SQL 的 RDBMS。 然而,不像 RDBMS 使用固定列表,IndexedDB 是一个基于 JavaScript 的面向对象数据库。IndexedDB 允许您存储和检索用键索引的对象;可以存储结构化克隆算法支持的任何对象。您只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务。

特性

  • 键值对存储:IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
  • 异步:IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
  • 支持事务:IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
  • 同源限制:IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  • 储存空间大:IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
  • 支持二进制储存:IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

优势

  • 大!大存储,大容量,支持更多类型
  • 同源策略的安全加持
  • 拥有更多交互的方式

劣势

  • API 心智成本较高

Cache API

概述

Cache API 严格意义上来说与前三者其实不是同一类事物,前三者关注的是主动存储的数据,而 Cache API 提供的是浏览器缓存的控制机制,Cache API 一般结合 Service Worker 使用,因为请求级别的缓存与具有页面拦截功能的 Service Worker 最合适

Cache API 的出现意味着开发者可以主动去控制浏览器对于资源请求的缓存内容
**

特性

  • 支持主动操控浏览器缓存

参考

Pengsha Ying

逝者如斯,故不舍昼夜