Web Storage 与 IndexedDB:该把数据放哪
浏览器的存储方案不少:Cookie、localStorage、sessionStorage、IndexedDB、Cache Storage。选错会带来容量、性能或隐私问题。
一张对比表
| 方案 | 容量 | 同步 | 生命周期 | 随请求发送 |
|---|---|---|---|---|
| Cookie | 4KB | 同步 | 可设过期 | 是 |
| localStorage | 5-10MB | 同步 | 永久,除非手动清 | 否 |
| sessionStorage | 5-10MB | 同步 | 标签页关闭即清 | 否 |
| IndexedDB | 数百 MB | 异步 | 永久 | 否 |
| Cache Storage | 较大 | 异步 | 永久 | 否 |
localStorage 的两个限制
同步阻塞:读写都在主线程。存一个几百 KB 的 JSON,会造成明显卡顿。大对象不要放这里。
只能存字符串:对象要 JSON.stringify,这也意味着无法保存 Date、Map、二进制数据,取回来还得手动还原类型。
localStorage.setItem('prefs', JSON.stringify({ theme: 'dark' }));
const prefs = JSON.parse(localStorage.getItem('prefs') || '{}');
IndexedDB 适合什么
结构化数据、大量记录、需要索引查询的场景。它的 API 是事件式的,直接写很啰嗦,通常用 idb 这类小库包一层:
import { openDB } from 'idb';
const db = await openDB('notes', 1, {
upgrade(db) { db.createObjectStore('items', { keyPath: 'id' }); }
});
await db.put('items', { id: 1, text: 'hello' });
什么数据不该放浏览器
- 密码、令牌的长期副本;
- 可以轻易伪造的权限标记;
- 未经脱敏的个人信息。
localStorage 对同源脚本完全开放,一次 XSS 就能全部读走。敏感数据应由服务端持有,前端只保存短期、可撤销的凭证。
一个实践原则
界面偏好放 localStorage,业务数据放服务端,离线缓存放 IndexedDB/Cache。 判断标准是这份数据丢了会不会影响用户——会,就不要只存在本地。