浏览器存储方案对比:Cookie、Web Storage 与 IndexedDB
浏览器存储方案对比:Cookie、Web Storage 与 IndexedDB
前端能用的存储就那么几种,但各自的设计目的完全不同。选型错误的代价很实际:我见过把几 MB 的用户数据塞 Cookie 的,每个请求都背着它来回跑,慢得莫名其妙。
Cookie:为请求而生的"小纸条"
Cookie 的本质不是存储,而是HTTP 协议的状态维持机制——服务器 Set-Cookie 之后,浏览器每次请求同域自动带上。这个特性决定了它的命运:
- 容量极小,约 4KB,每个域名下数量有限
- 每次请求自动携带,包括请求图片、CSS、接口——放多了全是带宽浪费
- 有过期时间;
HttpOnly防 JS 读取,Secure只在 HTTPS 下传输,SameSite控制跨站携带
所以 Cookie 的正确用法只有一种:存服务器需要读的小数据,典型就是登录态标识(session id / token)。纯前端用的数据放 Cookie 里,是拿它的副作用当功能用。
Web Storage:纯前端的键值对
localStorage.setItem('theme', 'dark')
localStorage.getItem('theme')
localStorage.removeItem('theme')
- 容量 5MB 左右(各浏览器不一),不参与请求,纯前端可用
localStorage持久保存,除非主动清除;sessionStorage只在当前标签页会话内有效,关页即清- API 是同步的,数据量大时会阻塞主线程
- 只能存字符串,对象要
JSON.stringify/JSON.parse
sessionStorage 有个反直觉的点:新开标签页不会共享,但刷新页面会保留,而且通过链接新开的标签页会拷贝一份当时的快照,之后各自独立。想做"多标签页共享的临时状态"别指望它。
另外两个常见坑:
- 隐私模式/用户禁用 Cookie 时,写 localStorage 可能直接抛异常,关键逻辑要 try/catch
- localStorage 没有过期机制,自己存的业务数据要带时间戳字段,读的时候判断
IndexedDB:前端的小型数据库
当数据到了"几万条记录、需要按字段查询"的级别,就该 IndexedDB 出场了:
- 容量大得多(一般是磁盘配额的一部分,几百 MB 起步)
- 支持索引、事务、范围查询,是正经的数据库
- 异步 API,不阻塞主线程
- 可以存结构化对象、Blob、ArrayBuffer
代价是原生 API 非常难用(事件回调套娃),实战一律上封装库,比如 localForage(API 和 localStorage 一样简单)或者 Dexie(功能全)。
// localForage 的 API 和 localStorage 几乎一致,但是异步的
import localforage from 'localforage'
await localforage.setItem('draft', { title: '未发布', content: '...' })
const draft = await localforage.getItem('draft')
选型速查
| 需求 | 选择 |
|---|---|
| 登录态、服务端要读的标识 | Cookie(HttpOnly) |
| 主题、语言等小配置 | localStorage |
| 表单草稿、一次性向导状态 | sessionStorage |
| 大量结构化数据、离线应用 | IndexedDB |
| 敏感数据 | 都不存,或者加密后存,XSS 面前前端存储是透明的 |
别忘了还有 Cache Storage
PWA 场景下缓存接口响应和静态资源用的是 Cache Storage,和上面几个是不同体系,配合 Service Worker 使用。这个博客的主题切换、阅读偏好用的都是 localStorage,够用了。
总结成一句话:Cookie 是给服务器看的,Web Storage 是给 JS 看的小数据,IndexedDB 是给应用用的大数据。想清楚"谁要读这个数据",选型就不会错。
看到这里了?如果这篇文章帮到过你
请我喝瓶可乐就好 🥤

评论0 条
还没有评论,来抢沙发~