在前端开发中,“让浏览器记住一些东西”几乎是所有稍微复杂一点的应用都会遇到的需求:保存用户登录状态、记录偏好设置、缓存接口数据、支持离线应用等。浏览器本地存储做得好,可以显著减少网络请求、提升页面性能和用户体验;做不好,则会很容易出现数据混乱、XSS 泄露隐私等问题。之前我只是对着其中的一两个用的比较多,熟悉一些,其他的只是知道,所以我现在就想做一个全面一些的对比总结。
一、为什么需要浏览器本地存储?
传统 Web 模式下,所有状态都由服务端维护,浏览器只是一个“渲染终端”。但随着前端单页应用、PWA 和离线应用的兴起,越来越多状态被下放到客户端管理,典型需求包括:
- 记住登录状态(Token、用户信息、权限等)
- 记录用户偏好(主题色、语言、布局等)
- 缓存接口数据,减少重复请求
- 在刷新或关闭页面后保留表单内容
- 支持弱网或离线场景下的使用
基于以上这些需求,我们就需要对传统的 Web 模式进行改进优化,即诞生了可以在客户端持久化数据,以减少对服务端的依赖,提高用户体验。
二、浏览器常见存储方式总览
目前主流浏览器中,前端常用的存储方案主要有:
CookielocalStoragesessionStorageIndexedDB- (以及更偏缓存方向的
Cache API,文末会顺带提一下)
可以从几个维度来对比这些方案:容量、生命周期、是否参与网络请求、安全性和易用性。
一个常见的理解是:
- 少量、与服务端强相关、需要随请求发送 → Cookie
- 少量、长期存在、只在前端用 → localStorage
- 少量、只在当前标签页会话内有效 → sessionStorage
- 大量、结构化、需要查询/索引/事务 → IndexedDB
三、前置核心:浏览器存储的基石 —— 同源策略
-
在介绍这四种方法前,我们需要对一个前置知识点进行介绍。
-
所有浏览器存储方案都严格受同源策略约束,这是浏览器安全的核心规则。同源指的是「协议 + 域名 + 端口」三者完全一致,不同源的站点之间,存储数据完全隔离,无法互相访问。
-
唯一的例外是 Cookie,可通过
Domain属性配置实现父子域名间的数据共享,其余存储方案均不支持跨子域名访问,这是选型时必须先明确的前提。
-
四、Cookie:最传统也最“重”的方案
1. Cookie 的特点
Cookie 是最早的浏览器存储方式之一,最初就是为了解决“HTTP 是无状态的”这一问题,用来在客户端和服务端之间共享一小段状态信息,维持客户端与服务端的会话状态,是唯一能自动在前后端同步的存储方案。
-
核心原理:
- Cookie 是服务端通过
Set-Cookie响应头发送到浏览器、并保存在本地的小块数据,浏览器下次向同一服务端发起符合规则的请求时,会自动将 Cookie 携带在Cookie请求头中,回传给服务端。
- Cookie 是服务端通过
-
典型特征:
-
容量很小:单个域名下总容量大约几 KB 级别
-
会自动随着同域 HTTP 请求发送给服务器
-
可以设置过期时间(Session Cookie / Persistent Cookie)
-
可以通过属性控制安全性(如
HttpOnly、Secure、SameSite)
-
2. 设置和读取 Cookie 的方式
我们可以通过两种方式操作 Cookie:
- 通过
document.cookie在浏览器端直接读写 - 通过服务端响应头
Set-Cookie下发
典型示例:
// 写入 Cookie
document.cookie = 'theme=dark; max-age=3600; path=/';
// 读取 Cookie(简单解析)
function getCookie(name) {
const pattern = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)');
const match = document.cookie.match(pattern);
return match ? decodeURIComponent(match[1]) : null;
}
const theme = getCookie('theme');
推荐在项目中封装一层 Cookie 工具函数,避免到处拼字符串
3. Cookie 的适用场景与注意事项
-
适用场景:
-
会话标识(Session ID)
-
短小的鉴权 Token(更推荐 HttpOnly + Secure)
-
简单的跨页面偏好设置(如果需要服务端也感知)
-
-
注意事项:
-
不要在 Cookie 中存放敏感的明文信息(如密码、完整个人信息)
-
Token 建议使用
HttpOnly,避免被 XSS 通过 JS 读取 -
过多、过大的 Cookie 会拖累所有同域请求的性能
-
五、localStorage:最常用的“持久储物柜”
1. 特点与限制
localStorage 是 HTML5 引入的 Web Storage API 中的一部分,它提供了一个简单的键值对存储空间,有如下特征:
- 与域名绑定,通常容量在 5MB 左右
- 数据持久存在,除非显式清除或用户清理浏览器数据
- 不随 HTTP 请求发送,仅在前端可见
- API 简单、同步执行(阻塞主线程)
- 仅支持字符串类型,需要手动处理序列化和反序列化
2. 基本用法示例
// 写入
localStorage.setItem('token', 'xxx-yyy-zzz');
// 读取
const token = localStorage.getItem('token');
// 删除某个 key
localStorage.removeItem('token');
// 清空所有
localStorage.clear();
如果要存对象,需要配合 JSON.stringify 和 JSON.parse:
const user = { id: 1, name: 'Alice', role: 'admin' };
localStorage.setItem('user', JSON.stringify(user));
const raw = localStorage.getItem('user');
const userObj = raw ? JSON.parse(raw) : null;
3. 使用场景与最佳实践
-
常见场景:
-
存放 UI 层配置(主题色、布局、语言)
-
缓存一些非敏感的接口数据(如字典项、热门列表)
-
记录用户上次访问的状态(如当前 Tab、分页页码)
-
-
实践建议:
-
避免把敏感信息(Access Token、用户隐私)长期明文放在 localStorage 中
-
封装统一的 Storage 工具,集中管理 key 名、版本号、过期策略
-
考虑数据膨胀对性能的影响,大量字符串读写会阻塞主线程
-
六、sessionStorage:会话级的临时存储
1. 特点
sessionStorage 与 localStorage API 几乎完全相同,但它的生命周期和作用范围不同:
- 只在当前标签页有效,标签页关闭即销毁
- 同一浏览器同一域名下的不同标签页互不共享
- 容量通常与 localStorage 相近(约 5MB)
- 同样是同步 API,字符串键值对存储
2. 典型用法示例
// 保存表单草稿
function saveDraft(formId) {
const form = document.querySelector(`#${formId}`);
const data = Object.fromEntries(new FormData(form).entries());
sessionStorage.setItem('form-draft', JSON.stringify(data));
}
function restoreDraft(formId) {
const form = document.querySelector(`#${formId}`);
const draftStr = sessionStorage.getItem('form-draft');
if (!draftStr) return;
const draft = JSON.parse(draftStr);
Object.keys(draft).forEach((key) => {
const input = form.elements.namedItem(key);
if (input) input.value = draft[key];
});
}
3. 使用场景
- 临时表单数据防丢(刷新页面不丢,关闭标签页就清)
- 页内导航时的数据中转(不想暴露在 URL 上)
- 某些只在当前会话内生效的状态(如一次性的向导步骤)
七、IndexedDB:浏览器内的“小型数据库”
如果某一应用需要存储大量数据(比如离线缓存大量列表、图片缩略图、聊天记录等),或者需要复杂的查询能力,仅靠 localStorage 就不够用了,我们需要另一个解决方法,即 IndexeDB。
1. IndexedDB 的特点
-
IndexedDB 是浏览器内置的 NoSQL 数据库,有以下能力:
-
支持存储大量数据,只受磁盘空间限制
-
支持二进制(Blob、ArrayBuffer)等任意 JS 对象
-
支持索引、范围查询、游标、事务等数据库特性
-
异步 API,不阻塞主线程
-
和域名绑定,安全隔离
-
对于传统的 客户端-服务器 应用,以上的这些功能通常是没有必要的。IndexedDB 适用于离线应用,可与 ServiceWorkers 和其他技术相结合使用。
2. 基本使用流程概览
本文不在于详细解释教会每一个方法的使用,所以我也不过多的去介绍用法,只是简单说一下步骤。
详细介绍与使用方法推荐在下面的文章学习,写的都很好:
https://zh.javascript.info/indexeddb https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
-
IndexedDB 的 API 相对繁琐,一般包含几个步骤:
-
打开数据库(
indexedDB.open),指定名称和版本 -
在
onupgradeneeded中创建对象存储(类似表)和索引 -
在
onsuccess中拿到数据库实例 -
发起读写事务(
db.transaction),执行增删改查
-
3. 适用场景
- 大型数据集的离线缓存(如文章列表、聊天记录)
- 大文件或二进制数据的本地存储(图片、音频切片)
- 需要复杂查询能力的客户端数据层(多字段筛选、排序)
八、如何选择合适的存储方式?
我们可以从这几个问题倒推,然后结合选择方法:
- 数据大小有多大?
- 几 KB:Cookie、Web Storage 都可以
- 几百 KB~MB:localStorage、sessionStorage
- 更大、甚至几十 MB:IndexedDB
- 需要被服务端感知吗?
- 需要:Cookie(随请求发送)
- 不需要:localStorage / sessionStorage / IndexedDB
- 数据的生命周期是怎样的?
- 只在当前会话/标签页内:sessionStorage
- 长期保留,用户下次访问还需使用:localStorage / IndexedDB
- 按过期时间控制,并服务端参与:Cookie
- 是否包含敏感信息?
- 敏感信息优先考虑存服务器 + 短期 Token,配合 HttpOnly Cookie
- 尽量避免在 localStorage 中长期存放敏感明文数据
-
一个常见的组合实践:
-
认证凭证:短期 Token 放在 HttpOnly Cookie 中(前端无权读),前端只负责根据“是否登录”调整 UI
-
UI 偏好/非敏感配置:localStorage
-
临时表单数据:sessionStorage
-
大批量列表缓存、离线功能:IndexedDB
-
九、安全与性能注意事项
1. XSS 与数据泄露
-
无论是 Cookie、localStorage 还是 IndexedDB,只要能被 JS 读写,就有可能在发生 XSS 时被攻击者窃取。建议:
-
对用户可输入的内容严格做 XSS 防御(转义、CSP 等)
-
不在可被 JS 读到的存储中保存高价值敏感数据
-
对关键数据做加密/签名(虽然前端加密本身也需要谨慎看待)
-
2. 存储配额与异常处理
-
不同浏览器的实际存储配额、策略有所不同:
-
超出配额时,写入会抛出异常
-
用户可能随时清理站点数据
-
隐身模式下的行为可能不同
-
-
因此实际使用时就需要考虑到这些,采取一些应对措施,比如:
-
封装一层安全读写:捕获异常、做降级处理
-
对关键数据设计“缺失时如何恢复”的逻辑(例如重新拉取接口)
-
3. 同步 API 的阻塞问题
-
localStorage/sessionStorage的读写是同步的,在大量或高频操作时可能造成主线程卡顿。建议:-
不在高频事件(如
scroll、mousemove)里直接操作 Storage -
尽量合并多次写入,做节流/防抖
-
对于大规模读写,考虑使用 IndexedDB 这种异步方案
-
喜欢的话,留下你的评论吧~