Django或Spring等服务器端框架主要使用会话(Session)管理来处理服务器端的状态,并通过Cookie来识别客户端。服务器管理状态是很方便的。

但在React、Vue、Angular等SPA(Single Page Application)环境中,客户端(浏览器)承担了很多角色。与服务器的通信主要通过API交换数据,而用户的状态或UI设置通常在客户端直接管理。

此时,需要决定数据存储在“哪里”,浏览器为此提供了几种存储方式。明确了解每种存储的特点和用途是高效的SPA开发的关键。

今天我们将了解浏览器的主要存储:Cookie、Local Storage、Session Storage以及IndexedDB




Cookie是浏览器存储的元老。最初是为了在客户端和服务器之间保持状态(Stateful)而设计的。

  • 特点:

    • 小容量: 限制约4KB,容量非常小。

    • 服务器传送: 最大的特点。Cookie会自动包含在所有HTTP请求中,并传送到服务器。这在服务器想要了解客户端状态时很有用,但也可能因为不必要的数据传输而降低性能。

    • 过期时间: 可以通过ExpiresMax-Age属性设置到期日期和时间。如果不设置,则作用为会话Cookie(浏览器关闭时删除)。

    • 安全选项: 可以设置HttpOnly(防止JavaScript访问)、Secure(只在HTTPS下传输)等安全设置。

  • 主要用途:

    • 认证 (Authentication): 存储服务器发出的登录认证令牌(JWT等),使得服务器可以在用户每次页面跳转时识别用户。(尤其是与HttpOnly选项一起使用)

    • 用户追踪及广告: 用于追踪用户的访问记录或行为模式。(例如:Google Analytics)

    • “今天不再显示”弹窗


2. Local Storage

这是HTML5推出的Web Storage API的一部分。为了弥补Cookie的缺点(容量小、自动服务器传送)而出现。

  • 特点:

    • 大容量: 每个浏览器不同,但通常提供5MB〜10MB的充足容量。

    • 不传送给服务器: Local Storage将数据仅保存在客户端,不会自动发送给服务器。适合存储服务器不需要了解的数据。

    • 持久性: 数据永久保留。除非用户手动删除浏览器缓存或通过JavaScript代码调用localStorage.removeItem(),否则数据不会消失。

    • 简便的API: 提供localStorage.setItem('key', 'value')localStorage.getItem('key')等易于使用的API。(只能存储字符串)

  • 主要用途:

    • 用户设置存储: 存储用户选择的UI设置,如深色模式/浅色模式设置、语言设置等。

    • 非敏感数据存储: 用户最近查看的内容列表、自动保存功能等。

    • 数据缓存: 缓存API响应中不常变更的数据,以减少不必要的请求。


3. Session Storage



与Local Storage几乎共享所有特点,但在数据的生命周期(Life Cycle)上有决定性差异。

  • 特点:

    • 大容量: 与Local Storage相同,约提供5MB的容量。

    • 不传送给服务器: 仅存储在客户端。

    • 基于会话的生命周期: 数据仅限于当前浏览器标签页(或窗口)。关闭标签后,Session Storage中的所有数据将立刻删除

    • 数据隔离: 同一域名下不同标签间不共享数据

  • 主要用途:

    • 一次性数据存储: 仅在当前标签中有效的信息。

    • 临时表单数据: 分多个步骤的会员注册表单或问卷填写时,用户在关闭标签前输入的内容临时存储。

    • 刷新时数据保留: 页面刷新时保持数据,但关闭标签后数据消失的场景。


4. IndexedDB

如果说Local Storage和Session Storage是简单的Key-Value存储,IndexedDB就是浏览器内存在真正的事务数据库系统

  • 特点:

    • 大容量存储: 可以存储从数百MB到数GB的数据,具体取决于用户的磁盘空间(根据浏览器政策而异)。

    • 多种数据类型: 可以存储的不仅是字符串,还包括JavaScript对象、文件(Blob)、数组等复杂结构的数据

    • 支持交易(Transaction): 确保数据的完整性和一致性。可以将多个操作作为一个单元进行处理。

    • 异步(Asynchronous) API: IndexedDB的所有操作都是异步处理的。这意味着在读取和写入大数据时也不会阻塞主UI线程,从而保持应用程序响应性。

    • 支持索引(Index): 可以创建索引以便根据特定字段快速搜索数据。

  • 缺点:

    • 复杂的API: 相比localStorage,API复杂且难以使用。(因此经常和Dexie.jsidb等包装器(Wrapper)库一起使用。)
  • 主要用途:

    • 离线Web应用程序(PWA): 存储需要在离线状态下工作的重要数据。(例如:离线文档编辑器)

    • 大规模应用状态缓存: Gemini或ChatGPT将在浏览器中存储以前的对话记录,或在管理复杂用户数据时使用。

    • 用户生成内容的临时存储: 在用户撰写长文本或编辑图像数据时安全保存到服务器上传之前。


5. 一目了然的比较

A conceptual diagram illustrating different types of web browser storage: Cookie, Local Storage, Session Storage, and IndexedDB, each with symbolic icons representing their characteristics within a stylized browser window.

四种存储的特点汇总如下表:

标准 Cookie Local Storage Session Storage IndexedDB
容量 ~ 4KB ~ 5-10MB ~ 5MB ~ GB+ (大容量)
过期时间 手动设置 永久性 关闭标签时 永久性
服务器传送 O (自动传送) X (客户端专用) X (客户端专用) X (客户端专用)
访问范围 同一域名 同源 当前标签 同源
数据形式 字符串 字符串 字符串 对象、文件、Blob等
API 同步 (复杂) 同步 (简便) 同步 (简便) 异步 (复杂)
搜索功能 X X X O (使用索引)

6. 结论: 何时使用什么?

在开发如React的SPA时,明确区分这四种存储的用途是很重要的。

  • Cookie:

    • 用于服务器必须知道的数据。(例如:安全性重要的认证令牌)

    • 使用HttpOnly选项来保护令牌免受XSS攻击是个好主意。

  • Local Storage:

    • 用于需要在用户重启浏览器后仍需保留的简单数据

    • (例如:用户UI主题设置、语言选择)

  • Session Storage:

    • 用于仅当前操作(标签)中需要的临时数据

    • (例如:多步骤表单填写中的临时保存)

  • IndexedDB:

    • 在需要结构化大数据离线支持时使用。

    • (例如:复杂的应用状态、对话记录缓存、离线文档数据)

重要安全提示: Local Storage、Session Storage和IndexedDB可以被JavaScript轻松访问。这意味着它们易受XSS(跨站脚本攻击)的威胁。切不可在此存储密码、个人识别信息、敏感认证令牌等。(认证令牌最好使用HttpOnly Cookie来存储,这样更安全。)