localstorage 版本控制需将版本信息作为数据字段嵌入结构化对象,统一用固定 key 存储;读取时必须同步校验 version 字段,不匹配则立即清除并返回 null;辅以空闲时低开销扫描和多标签页标志位机制防残留与竞争。

localStorage 本身不带版本概念,所有版本控制逻辑都得由开发者自己设计和维护。关键不是“给 localStorage 加版本”,而是把版本信息作为数据的一部分存进去,并在读写时主动比对、清理。
统一用结构化对象存储,嵌入 version 字段
不要把版本号塞进 key 名(比如 user_data_v2),那样旧数据永远残留,还难管理。正确做法是所有数据都存成一个带元信息的对象:
- 每次写入前,从构建环境或全局变量中读取当前应用版本(如
process.env.NEXT_PUBLIC_APP_VERSION或window.__APP_VERSION__) - 存入时包裹成标准结构:
{ value: data, version: "2.1.0", timestamp: Date.now() } - 用固定 key 存,比如
localStorage.setItem('user_settings', JSON.stringify(obj))
读取时强制校验,过期就删
每次调用 getItem 后不能直接用,必须先解析、再比对版本:
- 解析失败或
item.version !== currentVersion,就立即removeItem(key)并返回null - 避免“读出旧数据→渲染→才意识到该清”的问题,校验必须发生在使用前
- 这个动作是同步的,轻量且必要,不能省略
启动时轻量扫描,补漏 + 防堆积
只靠读取时清理会漏掉长期不用的 key(比如用户从未打开过的功能页缓存)。可在页面空闲时做一次低开销扫描:
- 用
requestIdleCallback触发,避免阻塞主线程 - 每次只检查前 20 个 key(用
localStorage.key(i)遍历),校验 version 和 timestamp - 记录上次扫描时间(如
last_version_scan),确保每天最多执行一次
多标签页下别依赖 storage 事件做主逻辑
标签页 A 清了缓存,会触发 storage 事件通知标签页 B,但这只是“某个 key 被删了”,不代表 B 的所有缓存都失效:
- B 可能刚读出 v1 数据,正准备渲染,事件来了也来不及中断
- 不要在事件里直接
location.reload()或清空全部 localStorage - 可设一个标志位(如
window.__CACHE_DIRTY = true),下次关键读取前检查并触发重载或重新初始化











