Web 应用把用户数据、离线目录和草稿状态缓存在 localStorage 与 IndexedDB 里,把浏览器当成记录数据库。在 WebView 里这个假设会崩塌:存储是尽力而为,从不保证。存储压力下浏览器会一次性清空整个源(LRU);Safari 在七天无交互后删除脚本可写存储;App 升级与重装会清空 WebView 数据目录;而内嵌在另一个 App 的 WKWebView 中的内容,配额大约只有总磁盘的 15%。宿主自有 runtime 提供受控持久化——服务端同步的存储、带版本的迁移,以及页面真正能依赖的耐久性保证。

存储压力:要么全有、要么全无的清除

按 Web 存储规范,当设备空间不足时,浏览器采用最近最少使用(LRU)策略,一次性删除整个源的全部存储——IndexedDB 与 Cache API 一起消失,而不是逐键删除。只有用 navigator.storage.persist() 申请到持久化的源能被跳过,而这个授权取决于参与度信号,常常静默返回 false。对应用内 WebView 而言更糟:实测数据显示,内嵌在另一个 App 的 WKWebView 中的 Web 内容,配额大约只有总磁盘的 15%,而独立浏览器 App 约为 60%。在 Safari 里安静运行的 PWA,到了内嵌视图里就会悄悄崩。

静默的七天清除,与内存陷阱

Safari 会主动清除脚本可写存储——包括 localStorage 和 sessionStorage——对任何在过去七天 Safari 使用中没有用户交互的站点,除非它被安装到主屏幕。另一面是,部分 iOS 容器 App 让 WKWebView 的数据存储停留在非持久化(内存级)配置,于是 localStorage 在进程退出或 App 退到后台的瞬间就没了。写入在会话期间看似成功,之后数据干脆不在了。混合开发团队经常发现令牌与偏好在切换后台或 App 升级后莫名消失。

存储蒸发时,你会失去什么

  • 离线目录消失。 缓存的商品列表与文章在压力下被清掉,App 退化成转圈圈。
  • 草稿丢失。 写了一半的表单和未同步的编辑毫无预警地没了。
  • 静默登出。 存在 localStorage 里的令牌被清空,在最糟的时刻被迫重新登录。
  • 迁移断裂。 清空数据目录或重建 WebView 的 App 升级,可能把用户卡在 schema 版本之间。
  • 没有耐久性契约。 localStorage 是同步的,每源约 5MB 上限,并抛出 QuotaExceededError——它从来不是记录数据库。

runtime 解法

宿主自有 runtime 不再把 WebView 当作真相来源。它在页面之下提供一套服务端同步的存储:关键状态在原生层持久化(扛过升级、重装与系统清理),加载时镜像进页面,并在 schema 变更时用显式版本号做迁移。H5 仍用熟悉的 localStorage 形态 API,但 runtime 保证了 WebView 给不了的耐久性。

维度WebView宿主自有 runtime
持久化保证尽力而为,无耐久,原生层
存储压力整源清除服务端同步,安全
App 升级/重装清空数据目录存活
iOS 七天规则删除存储原生存储豁免
应用内配额约总磁盘 15%宿主可控
迁移安全脆弱带版本

浏览器的存储 API 承诺的是便利,不是耐久。裸 WebView 连这点便利都悄悄拿走。runtime 把「失忆盒子」变成真正的存储——一个能跨升级、重装与低磁盘日而让页面信赖的存储。

参考来源