浏览器存储配额和淘汰机制是怎样的?前端离线数据如何设计?
简化版
浏览器本地存储不是无限空间,IndexedDB、Cache Storage、localStorage 等都会受到配额和淘汰策略影响。离线数据设计要估算体积、处理写入失败、区分关键数据和可重建缓存,并提供清理、版本迁移和服务端同步兜底。
详细版
要点:
- localStorage 容量小且同步阻塞,不适合大数据。
- IndexedDB 适合结构化离线数据。
- Cache Storage 适合请求/响应缓存。
- 浏览器可能因磁盘压力、站点使用频率、隐私模式等清理数据。
- 关键数据不能只存在浏览器本地。
设计建议:
- 使用
navigator.storage.estimate()估算空间。 - 缓存分层:关键草稿、可重建资源、临时数据。
- 写入失败要兜底。
- 给缓存加版本和过期策略。
- 用户可清理,服务端可恢复。
完整版教学
一、本地存储不是小硬盘
浏览器提供 localStorage、IndexedDB、Cache Storage、OPFS 等本地存储能力,但它们不是完全属于你的网站的小硬盘。浏览器会根据设备空间、站点活跃度、隐私模式和自身策略限制使用量,必要时可能清理部分数据。
因此离线设计不能假设“写进浏览器就永远在”。它更适合作为缓存、草稿、离线队列或性能优化层,关键业务事实仍应尽快同步到服务端。
服务端事实数据
↑ ↓
本地缓存 / 草稿 / 离线队列
↑
浏览器配额和淘汰策略约束
二、不同存储适合不同数据
localStorage 简单但同步阻塞,容量小,适合少量配置;IndexedDB 异步、容量更大,适合结构化数据;Cache Storage 适合缓存请求响应;Cookie 会随请求发送,不适合大数据。选错存储会带来性能和稳定性问题。
| 存储 | 适合 | 不适合 |
|---|---|---|
| localStorage | 少量配置、开关 | 大对象、高频读写 |
| IndexedDB | 离线表、草稿、队列 | 简单临时变量 |
| Cache Storage | 静态资源、接口响应 | 复杂查询 |
| Cookie | 会话标识 | 大数据和敏感明文 |
如果把 2MB JSON 放进 localStorage,每次同步读写都会阻塞主线程;放到 IndexedDB 更合适。
三、配额要能估算和观测
浏览器提供 navigator.storage.estimate() 查询当前 origin 的估算使用量和配额。不同浏览器、设备和模式下结果差异很大,不能写死“有 50MB”。
if (navigator.storage?.estimate) {
const { usage, quota } = await navigator.storage.estimate()
console.log(`used=${usage}, quota=${quota}`)
}
数字例子:如果离线缓存 1000 篇文章,每篇正文和索引约 80KB,总计约 80MB;再缓存图片可能轻松超过 300MB。没有配额估算和清理策略,低存储设备上很容易写入失败。
四、淘汰机制要求缓存可重建
浏览器在存储压力下可能清理某些站点数据。具体策略因浏览器而异,常见考虑包括是否持久化授权、站点活跃度和空间压力。你不能假设 Cache Storage 里的资源永远存在。
因此缓存必须可重建。静态资源丢了可以重新下载,接口缓存过期可以重新请求,离线草稿则要尽快同步服务端或提示用户风险。缓存数据最好有版本和过期时间,避免旧结构长期残留。
五、写入失败要成为正常分支
存储写入可能失败:配额满、隐私模式限制、浏览器异常、用户清理数据。代码不能只写 happy path。保存草稿失败时应提示用户,缓存写失败可以降级为在线模式,离线队列写失败则要阻止用户误以为提交成功。
try {
await saveDraftToIndexedDB(draft)
} catch (err) {
showToast('本地草稿保存失败,请尽快提交或复制内容')
}
六、离线数据要分层管理
离线数据可以分为三层:关键草稿、业务队列、可重建缓存。关键草稿要优先保存并提示同步状态;业务队列要有幂等 ID 和重试机制;可重建缓存可以按 LRU 或过期时间清理。
例如离线问卷有 20 个字段,用户填写 10 分钟后断网。草稿丢失会严重伤害体验;而首页推荐列表缓存丢失只是重新加载慢一点。不同数据价值不同,清理策略也不同。
记忆钩子:浏览器本地存储是“可丢的缓存层”,只有同步到服务端或可恢复的数据才安心。
七、常见误区与追问
- 误区:IndexedDB 容量很大,所以可以无限存。 它仍受浏览器配额和设备空间限制,写入可能失败。
- 误区:localStorage 简单,适合所有本地数据。 它同步阻塞且容量小,不适合大对象和高频写入。
- 误区:离线数据存在本地就安全。 用户清缓存、隐私模式、设备更换都会导致数据不可用。
- 追问:如何查看当前存储使用量? 使用
navigator.storage.estimate()获取估算 usage 和 quota。 - 追问:缓存满了怎么清理? 按数据价值、过期时间、LRU 和版本清理,优先保留关键草稿。
- 追问:离线提交如何避免重复? 本地队列带幂等 ID,服务端按 ID 去重,成功后清理本地记录。
八、加强记忆
浏览器存储用“选对容器、估算配额、接受可丢、关键同步”来记。localStorage 放小配置,IndexedDB 放结构化离线数据,Cache Storage 放资源和响应缓存;写入失败要处理,缓存要能重建,真正重要的数据要同步服务端。