存储配额和驱逐标准
Web 开发者可以使用多种技术在用户的浏览器(即用户用来查看网站的设备的本地磁盘)中存储数据。
浏览器允许网站存储的数据量以及它们在达到该限制时用于删除数据的机制在不同浏览器之间有所不同。
本文介绍了可用于存储数据的 Web 技术、浏览器为限制网站存储过多数据而设置的配额,以及它们在需要时用于删除数据的机制。
浏览器如何将来自不同网站的数据分开?
浏览器将来自网站的数据存储在不同的位置,也称为桶,以降低用户在网络上被跟踪的风险。在大多数情况下,浏览器按源管理存储的数据。
因此,了解本文中的源一词非常重要。源由方案(例如 HTTPS)、主机名和端口定义。例如,https://example.com
和 https://example.com/app/index.html
属于同一个源,因为它们具有相同的方案 (https
)、主机名 (example.com
) 和默认端口。
本文中描述的配额和驱逐标准适用于整个源,即使该源用于运行多个网站,例如 https://example.com/site1/
和 https://example.com/site2/
。
然而,在某些情况下,浏览器可能会决定将源存储的数据进一步分离到不同的分区中,例如,当一个源在多个不同的第三方源的 <iframe>
元素中加载时。但是,为了简化起见,本文假设数据始终按源存储。
哪些技术在浏览器中存储数据?
Web 开发者可以使用以下 Web 技术在浏览器中存储数据
技术 | 描述 |
---|---|
Cookie | HTTP Cookie 是一小段数据,Web 服务器和浏览器在跨页面导航时互相发送,以记住有状态的信息。 |
Web 存储 | Web 存储 API 提供了机制,让网页存储仅字符串的键值对,包括 localStorage 和 sessionStorage 。 |
IndexedDB | IndexedDB 是一个 Web API,用于在浏览器中存储大型数据结构并对其进行索引,以实现高性能搜索。 |
缓存 API | 缓存 API 为 HTTP 请求和响应对象对提供持久存储机制,用于加快网页加载速度。 |
源私有文件系统 (OPFS) | OPFS 提供一个文件系统,该文件系统对页面的源是私有的,可用于读取和写入目录和文件。 |
请注意,除了上述内容之外,浏览器还会为源在浏览器中存储其他类型的数据,例如 WebAssembly 代码缓存。
浏览器存储的数据是否持久化?
源的数据可以在浏览器中以两种方式存储:持久化和尽力而为
- 尽力而为:这是默认存储数据的方式。尽力而为的数据会一直保留,只要源低于其配额、设备有足够的存储空间,并且用户没有选择通过浏览器的设置删除数据。
- 持久化:源可以选择以持久的方式存储其数据。以这种方式存储的数据只有在用户选择使用浏览器的设置时才会被驱逐或删除。要了解更多信息,请参阅 何时驱逐数据。
浏览器中源存储的数据默认情况下为尽力而为。使用 IndexedDB 或缓存等 Web 技术时,数据会透明地存储,无需请求用户的许可。同样,当浏览器需要驱逐尽力而为的数据时,它会这样做,不会中断用户。
如果出于任何原因,开发者需要持久存储(例如,当构建一个依赖于未在其他地方持久化的关键数据的 Web 应用程序时),他们可以使用 navigator.storage.persist()
方法,该方法属于 存储 API。
在 Firefox 中,当一个网站选择使用持久存储时,用户会收到一个 UI 弹出窗口,提示需要他们的许可。
Safari 和大多数基于 Chromium 的浏览器(例如 Chrome 或 Edge)会根据用户与网站交互的历史记录自动批准或拒绝请求,并且不会向用户显示任何提示。
请注意,来自 Chrome 团队的研究表明,浏览器很少删除数据。如果用户定期访问某个网站,那么其存储的数据(即使是在尽力而为模式下)被浏览器驱逐的可能性非常小。
私密浏览
请注意,在私密浏览模式(在 Chrome 中也称为隐身,在 Edge 中也称为InPrivate)下,浏览器可能会应用不同的配额,并且存储的数据通常在私密浏览模式结束时会被删除。
可以存储多少数据?
Cookie
不同的浏览器对每个源允许的 Cookie 数量以及这些 Cookie 在磁盘上可以使用的空间有不同的规则。虽然 Cookie 有助于在页面导航时保留浏览器和 Web 服务器之间的一些小型共享状态,但建议不要将 Cookie 用于在浏览器中存储数据。Cookie 会随着每个 HTTP 请求发送,因此在 Cookie 中存储可以通过使用其他 Web 技术存储的数据会不必要地增加请求的大小。
由于 Cookie 不应该用于在浏览器中存储数据,因此本文中不介绍 Cookie 存储浏览器限制。
Web 存储
Web 存储可以通过使用 localStorage
和 sessionStorage
属性访问,这些属性属于 window
对象,在所有浏览器上最多限制为 10 MiB 的数据。
浏览器可以为每个源存储最多 5 MiB 的本地存储和 5 MiB 的会话存储。
一旦达到此限制,浏览器就会抛出 QuotaExceededError
异常,应使用 try...catch
块进行处理。
其他 Web 技术
使用其他 Web 技术(例如 IndexedDB、缓存 API 或文件系统 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
从 macOS 14 和 iOS 17 开始,Safari 为每个源分配大约 20% 的总磁盘空间。如果用户将其保存为 Home Screen 或 Dock 上的 Web 应用程序,则此限制会增加到磁盘大小的 60%。出于隐私原因,跨源框架具有单独的配额,大约是其父框架的 1/10。
例如,具有 1 TiB 驱动器的 macOS 设备将每个源限制为大约 200 GiB。如果用户将 Web 应用程序存储在其 Dock 上,则该 Web 应用程序将分配一个更大的限制,大约为 600 GiB。
与其他浏览器一样,配额执行的确切限制可能会有所不同,以避免指纹识别。此外,Safari 还执行一个总体配额,所有源存储的数据都不能超过该配额:每个浏览器和 Web 应用程序的磁盘大小的 80%,以及每个显示 Web 内容的非浏览器应用程序的磁盘大小的 15%。有关 Safari 存储策略的更多信息,请访问 Webkit 博客。
在早期版本的 Safari 中,会为源分配初始的 1 GiB 配额。一旦源达到此限制,Safari 就会向用户请求许可,以允许源存储更多数据。无论源是存储在尽力而为模式下还是持久模式下,都会发生这种情况。
如何检查可用空间?
Web 开发者可以使用 navigator.storage.estimate()
方法(属于 存储 API)来检查源有多少可用空间以及源正在使用多少空间。
请注意,此方法仅返回估计的用量值,而不是实际值。某些由来源存储的资源可能来自其他来源,并且浏览器在报告总用量值时会自愿填充跨来源数据的尺寸。
当一个源填满其配额时会发生什么?
例如,尝试使用 IndexedDB、缓存或 OPFS 存储超过来源配额的存储会导致 QuotaExceededError
异常。
Web 开发人员应将写入浏览器存储的 JavaScript 代码封装在 try...catch
代码块中。建议在存储新数据之前删除数据以释放空间。
何时驱逐数据?
数据清除是浏览器删除来源存储数据的过程。
数据清除可能发生在多种情况下
- 当设备存储空间不足时,也称为存储压力。
- 当浏览器中存储的所有数据(跨所有来源)超过浏览器愿意在设备上使用的总空间时。
- 主动清除,针对不经常使用的来源,仅在 Safari 中发生。
存储压力清除
当设备存储空间不足时,也称为存储压力,浏览器可能无法存储所有来源存储的数据。
浏览器使用最近最少使用 (LRU) 策略来处理这种情况。会删除最近最少使用的来源的数据。如果存储压力持续存在,浏览器将继续删除第二少使用的来源,依此类推,直到问题解决。
这种清除机制仅适用于非持久性来源,并且会跳过通过使用 navigator.storage.persist()
被授予数据持久性的来源。
浏览器最大存储空间超过清除
一些浏览器定义了它们可以在设备硬盘上使用的最大存储空间。例如,Chrome 目前最多使用总磁盘大小的 80%。
此最大存储空间意味着,所有来源存储的总数据量可能会超过最大大小,而没有单个来源超过其个人配额。
当这种情况发生时,浏览器会根据 存储压力清除 中的说明,开始尽力清除来源。
主动清除
Safari 在启用跨站点跟踪预防时会主动清除数据。如果来源在过去七天的浏览器使用过程中没有用户交互,例如点击或点击,则其从脚本创建的数据将被删除。服务器设置的 Cookie 不受此清除的影响。
如何驱逐数据?
当浏览器清除来源数据时,其所有数据,而不是部分数据,会同时被删除。例如,如果来源使用 IndexedDB 和缓存 API 存储数据,则这两种类型的数据都会被删除。
只删除来源的部分数据可能会导致不一致问题。