存储配额和逐出标准

Web 开发者可以使用多种技术在用户的浏览器中存储数据(即,在用户查看网站所用设备的本地磁盘上)。

不同浏览器允许网站存储的数据量以及达到该限制时删除数据的机制有所不同。

本文介绍了可用于存储数据的 Web 技术、浏览器为限制网站存储过多数据而设置的配额,以及必要时删除数据的机制。

浏览器如何分离来自不同网站的数据?

浏览器将来自不同网站的数据存储在不同的位置(也称为“桶”),以降低用户在网络上被跟踪的风险。在大多数情况下,浏览器会按源(per origin)管理存储的数据。

因此,要理解本文,源(origin)这个术语非常重要。源由协议(如 HTTPS)、主机名和端口定义。例如,https://example.comhttps://example.com/app/index.html 属于同一个源,因为它们有相同的协议(https)、主机名(example.com)和默认端口。

本文中描述的配额和清除标准适用于整个源,即使该源用于运行多个网站,例如 https://example.com/site1/https://example.com/site2/

然而,在某些情况下,浏览器可能会决定将一个源存储的数据进一步划分到不同的分区中,例如当一个源在多个不同的第三方源中的 <iframe> 元素内加载时。但为简单起见,本文假定数据总是按源存储。

哪些技术可以在浏览器中存储数据?

Web 开发者可以使用以下 Web 技术在浏览器中存储数据

技术 描述
Cookie HTTP Cookie 是一小段数据,Web 服务器和浏览器相互发送,用于在页面导航之间记住有状态的信息。
Web Storage Web Storage API 提供了网页存储纯字符串键值对的机制,包括 localStoragesessionStorage
IndexedDB IndexedDB 是一种 Web API,用于在浏览器中存储大量结构化数据,并为其建立索引以实现高性能搜索。
Cache API Cache API 为 HTTP 请求和响应对象对提供了一种持久化存储机制,用于加快网页加载速度。
源私有文件系统(OPFS) OPFS 提供了一个对页面源私有的文件系统,可用于读写目录和文件。

请注意,除上述技术外,浏览器还会为一个源在浏览器中存储其他类型的数据,例如WebAssembly代码缓存。

浏览器存储的数据是否持久?

一个源的数据在浏览器中可以通过两种方式存储:持久化(persistent)尽力而为(best-effort)

  • 尽力而为(Best-effort):这是数据默认的存储方式。只要源的用量低于其配额、设备有足够的存储空间,且用户没有通过浏览器设置选择删除数据,尽力而为的数据就会一直存在。
  • 持久化(Persistent):一个源可以选择以持久化的方式存储其数据。以这种方式存储的数据只有在用户通过浏览器设置选择删除时才会被清除。要了解更多信息,请参阅数据何时会被清除

默认情况下,源在浏览器中存储的数据是尽力而为的。当使用 IndexedDB 或 Cache 等 Web 技术时,数据会以透明的方式存储,无需征求用户许可。同样,当浏览器需要清除尽力而为的数据时,它也会在不打扰用户的情况下进行。

如果开发者出于任何原因需要持久化存储(例如,在构建依赖于未在别处持久化的关键数据的 Web 应用时),他们可以使用Storage APInavigator.storage.persist()方法。

在 Firefox 中,当一个网站选择使用持久化存储时,会弹出一个 UI 提示框通知用户,请求其许可。

Safari 和大多数基于 Chromium 的浏览器(如 Chrome 或 Edge)会根据用户与网站的交互历史自动批准或拒绝请求,并且不会向用户显示任何提示。

注意,Chrome 团队的研究表明,浏览器很少会删除数据。如果用户经常访问一个网站,即使是在尽力而为模式下,其存储的数据被浏览器清除的可能性也非常小。

隐私浏览

请注意,在隐私浏览模式下(在 Chrome 中称为无痕模式,在 Edge 中称为 InPrivate),浏览器可能会应用不同的配额,并且存储的数据通常会在隐私浏览模式结束时被删除。

可以存储多少数据?

Cookie

不同的浏览器对于每个源允许的 Cookie 数量以及这些 Cookie 可以在磁盘上使用的空间有不同的规定。虽然 Cookie 对于在浏览器和 Web 服务器之间跨页面导航保留一些小的共享状态很有用,但不建议使用 Cookie 在浏览器中存储数据。Cookie 会随每个 HTTP 请求发送,因此将本可以使用其他 Web 技术存储的数据存放在 Cookie 中,会不必要地增加请求的大小。

因为 Cookie 不应用于在浏览器中存储数据,所以这里不讨论 Cookie 存储的浏览器限制。

Web Storage

Web Storage,可以通过window对象的localStoragesessionStorage属性访问,在所有浏览器中最多限制为 10 MiB 数据。

浏览器每个源最多可以存储 5 MiB 的本地存储和 5 MiB 的会话存储。

一旦达到此限制,浏览器会抛出一个 QuotaExceededError 异常,应使用 try...catch 块来处理。

其他 Web 技术

使用其他 Web 技术(如 IndexedDB、Cache API 或 File System API(它定义了源私有文件系统))存储的数据由每个浏览器特有的存储管理系统进行管理。

该系统管理着一个源使用这些 API 存储的所有数据。

每个浏览器都通过其选择的任何机制来确定给定源可以使用的最大存储量。

Firefox

在 Firefox 中,一个源在尽力而为模式下可以使用的最大存储空间是以下两者中的较小值:

  • 存储用户配置文件的总磁盘大小的 10%。
  • 或 10 GiB,这是 Firefox 对属于同一个eTLD+1 域的所有源应用的组限制

已获得持久化存储权限的源最多可以存储总磁盘大小的 50%,上限为 8 TiB,并且不受 eTLD+1 组限制的约束。

例如,如果设备有一个 500 GiB 的硬盘,Firefox 将允许一个源最多存储:

  • 在尽力而为模式下:10 GiB 的数据,即 eTLD+1 组限制。
  • 在持久化模式下:250 GiB,即总磁盘大小的 50%。

请注意,源实际上可能无法达到其配额,因为配额是基于硬盘大小计算的,而不是当前可用的磁盘空间。这样做是出于安全原因,以避免指纹识别

Chrome 及基于 Chromium 的浏览器

在基于Chromium 开源项目的浏览器中,包括 Chrome 和 Edge,一个源在持久化和尽力而为模式下最多可以存储总磁盘大小的 60%。

例如,如果设备有一个 1 TiB 的硬盘,浏览器将允许一个源最多使用 600 GiB。

与 Firefox 类似,由于此配额是基于硬盘总大小计算以避免指纹识别,一个源实际上可能无法达到其配额。

Safari

WebKit 对浏览器应用和其他可以嵌入 Web 内容的应用(例如,使用 WKWebView 的应用)施加了不同的配额。浏览器应用是可以设置为系统默认浏览器的应用程序。这包括 Safari 和一些其他基于 WebKit 的第三方浏览器。

从 macOS 14 和 iOS 17 开始

  • 对于基于 WebKit 的浏览器应用,每个源最多可以存储总磁盘空间的 60% 左右。
  • 对于其他嵌入 Web 内容的基于 WebKit 的应用,每个源最多可以存储总磁盘空间的 15% 左右。如果用户已将网站作为 Web 应用保存到主屏幕或程序坞,则它使用与浏览器应用相同的源配额(约占磁盘空间的 60%)。

例如,一台配备 1 TiB 硬盘的 macOS 设备将限制 Safari 浏览器内每个源的存储空间约为 600 GiB。而在另一个应用内嵌的 WebView 中运行的源将被分配一个较小的限制,约为 150 GiB。

出于隐私原因,跨源 iframe 有一个单独的配额,约为其父级配额的 1/10。

与其他浏览器一样,为避免指纹识别,配额强制执行的确切限制可能会有所不同。

WebKit 还强制执行一个总体配额,即所有源存储的数据总量不能超过浏览器应用磁盘大小的 80%,以及显示 Web 内容的非浏览器应用磁盘大小的 20%。

有关 WebKit 存储策略的更多信息,请访问 WebKit 博客

在早期版本的 Safari 中,一个源被给予初始的 1 GiB 配额。一旦源达到此限制,Safari 会请求用户允许该源存储更多数据。无论源是以尽力而为模式还是持久化模式存储数据,都会发生这种情况。

注意:在 iOS/iPadOS 上,第三方浏览器历来必须使用 WebKit,因此这些 WebKit 配额也适用于它们以及 Safari。在欧盟地区(iOS 17.4+),Apple 允许使用替代浏览器引擎;在这种情况下,将适用这些浏览器自身的引擎策略,而非 WebKit 的策略。

在 macOS 上,非 WebKit 浏览器(例如 Chromium/Firefox)使用它们自己的存储策略。

有关欧盟特定信息的更多详情,请访问Apple 开发者支持页面

如何检查可用空间?

Web 开发者可以使用Storage APInavigator.storage.estimate()方法来检查其源的可用空间以及已被使用的空间。

请注意,此方法仅返回估算的使用值,而非实际值。一个源存储的某些资源可能来自其他源,浏览器在报告总使用值时会有意地对跨源数据的大小进行填充。

当一个源的配额用满时会发生什么?

例如,尝试使用 IndexedDB、Cache 或 OPFS 存储超过源配额的数据会失败,并抛出 QuotaExceededError 异常。

Web 开发者应将写入浏览器存储的 JavaScript 代码包装在 try...catch 块中。同时建议在存储新数据之前通过删除数据来释放空间。

数据何时会被清除?

数据清除是浏览器删除一个源所存储数据的过程。

数据清除可能在多种情况下发生:

  • 当设备存储空间不足时,也称为存储压力(storage pressure)
  • 当浏览器中存储的所有数据(跨所有源)总量超过浏览器愿意在设备上使用的总空间时。
  • 对不经常使用的源进行主动清除,这种情况仅在 Safari 中发生。

存储压力清除

当设备存储空间不足时,也称为存储压力(storage pressure),可能会出现浏览器可用空间不足以存储所有源数据的情况。

浏览器使用最近最少使用(LRU)策略来处理这种情况。最近最少使用的源的数据会被删除。如果存储压力持续存在,浏览器会继续处理次近最少使用的源,以此类推,直到问题解决。

此清除机制仅适用于非持久化的源,并会跳过已通过 navigator.storage.persist() 获得数据持久化权限的源。

浏览器最大存储空间超限清除

一些浏览器定义了它们可以在设备硬盘上使用的最大存储空间。例如,Chrome 目前最多使用总磁盘大小的 80%。

这个最大存储大小意味着,可能会出现所有源存储的数据总量超过了最大值,而没有任何一个源超过其自身配额的情况。

当这种情况发生时,浏览器会开始清除尽力而为的源,如存储压力清除中所述。

主动清除

当开启跨站跟踪预防功能时,Safari 会主动清除数据。如果一个源在过去七天的浏览器使用中没有用户交互(如点击或轻触),其通过脚本创建的数据将被删除。由服务器设置的 Cookie 不受此清除规则影响。

数据是如何被清除的?

当一个源的数据被浏览器清除时,是其所有数据同时被删除,而不是部分数据。例如,如果该源同时使用了 IndexedDB 和 Cache API 存储数据,那么这两种类型的数据都会被删除。

仅删除源的部分数据可能会导致不一致问题。

另见