浏览器缓存外部JS文件策略

Gemini
Gemini

浏览器缓存外部 JavaScript 文件:跨域共享与分区机制的深度解析

执行摘要

本报告旨在解答一个对网络开发者和性能工程师至关重要的问题:浏览器缓存外部 JavaScript 文件是否仍按域名进行共享,从而使不同顶级域名能够从同一文件的缓存中受益。对于现代浏览器而言,明确的答案是否定的。由于浏览器架构中一项名为缓存分区(或称双键缓存)的根本性转变,像 share.com/a.js 这样的资源,当被 a.com 加载时,将与被 b.com 加载的同一资源分开缓存。这一变化已在主流浏览器(Chrome、Firefox、Safari)中普遍实现,它是对不断演进的隐私和安全担忧的直接回应,旨在防止利用传统共享缓存模型进行的跨站追踪和侧信道攻击。虽然这显著增强了用户隐私,但也带来了一定的权衡,导致常用第三方资源的缓存命中率降低和带宽消耗增加。本报告将深入探讨浏览器缓存的机制、推动分区实现的必要性、其对各种网络 API 的广泛影响,并为适应这一以隐私为先的新网络格局提供可操作的开发建议。

1. 浏览器缓存简介

浏览器缓存是优化网络性能的基石机制,它能显著缩短页面加载时间、最大程度地减少带宽消耗,并提升用户体验。其核心在于将网页资源临时存储在用户的本地设备上,以便将来更快地访问。

1.1 核心原理与优势

浏览器缓存充当一个临时本地存储空间,其本质是一个包含已下载网页资源(如图片、视频、CSS 和 JavaScript 文件)的小型数据库 1。当浏览器请求内容时,它首先会检查其本地缓存。如果内容存在且“新鲜”(即未过期),则直接从缓存中提供,从而完全绕过服务器 1。这个过程带来了显著的性能提升,并减轻了服务器的负载。内容如果其过期日期已过,则被视为“陈旧”,需要重新验证或从服务器重新获取 1。资源可以从“内存缓存”(例如,在软刷新后)或“磁盘缓存”(例如,在重新打开浏览器标签页后)加载,这表明了浏览器内部不同的存储层级 2。

1.2 关键 HTTP 缓存机制与头部

网络开发者和管理员通过使用特定的 HTTP 头部来指示浏览器如何缓存资源,包括何时缓存、何时不缓存以及缓存多长时间 1。

  • 强缓存: 这种策略允许浏览器在不与服务器重新验证的情况下提供缓存资源,前提是该资源仍然“新鲜”。它主要由 Expires 和 Cache-Control 头部控制 2。
    • Expires:一个较旧的 HTTP/1.0 头部,指定了资源过期的固定日期/时间。它的准确性可能受到客户端-服务器时间差异的影响 2。
    • Cache-Control:在 HTTP/1.1 中引入,这是更现代和首选的头部,它优先于 Expires 1。它提供了多种指令:
      • max-age:定义了资源在缓存中可以保留的最大时间(以秒为单位),超过此时间后需要重新验证 1。
      • no-cache:允许缓存响应,但在提供资源之前必须首先向源服务器提交验证请求 1。
      • no-store:完全禁止缓存内容,通常用于敏感或频繁变化的数据 1。
      • public:将内容标记为可由任何缓存(浏览器、代理)缓存 1。
      • private:将内容标记为私有,意味着它只能由客户端浏览器缓存,而不能由中间代理等缓存,通常用于用户相关数据 1。
  • 协商缓存(条件缓存): 如果强缓存规则不适用或已过期,浏览器会向服务器发送请求以检查其缓存副本是否仍然有效。如果内容未更改,服务器将返回 304 Not Modified 状态码,从而避免完整资源下载 2。这依赖于:
    • ETag:特定资源版本的标识符(令牌)。如果客户端的 ETag 与服务器的匹配,则返回 304 1。
      ETag 优先于 Last-Modified 2。
    • Last-Modified:指示资源的最后修改日期。浏览器发送 If-Modified-Since 头部,如果它匹配,则返回 304 2。
  • 启发式缓存: 如果既没有 Expires 也没有 Cache-Control 头部,但存在 Last-Modified,浏览器可能会应用一种启发式算法(例如,(currentTime - lastModified) * 0.1)来确定缓存的有效性 2。
  • 实现方式: 缓存策略可以通过 Web 服务器配置(例如 Apache2、Nginx)或直接在服务器端脚本(例如 PHP)中定义 1。

HTTP 缓存头部在网络性能优化中扮演着双重角色。最初,像 Cache-Control 和 Expires 这样的头部主要被设计用于提升性能,通过减少服务器负载和加速用户体验来实现。然而,private 指令的引入,明确指出标记为 private 的内容只能由浏览器缓存,而不能由代理等共享缓存存储,通常用于“用户相关数据”或“个性化内容” 1。这揭示了在缓存机制中对隐私问题的早期但有限的认识。即使在广泛推行“分区”概念之前,业界就已经认识到某些数据不应被不加区分地共享或存储在公共缓存中。这种认识预示了后来更全面的、由隐私驱动的分区策略。它表明,关于“私有”数据影响缓存的概念早已存在于 HTTP 标准中,但其范围和强制机制已随着新的隐私威胁而显著扩展。这突出了一条演进路径,即以性能为中心的功能逐渐融入了隐私考量。

此外,缓存头部的相互作用及其演进也值得关注。相关资料指出,Cache-Control 优先于 Expires 2,而

ETag 优先于 Last-Modified 2。这不仅仅是新功能的简单堆砌,它反映了 HTTP 协议本身的持续改进和演变 5。协议不断适应以解决局限性(例如,

Expires 在客户端-服务器时间同步方面的潜在问题 2),并提供更精细、更健壮的缓存控制。这种持续的演进对于网络适应不断变化的需求至关重要,这些需求包括性能、安全和隐私。它强调了网络标准并非一成不变,而是响应实际挑战和新兴威胁的动态文档。


表 2: 关键 HTTP 缓存头部及其指令

头部 类型 目的 常见指令 描述
Cache-Control 请求/响应 HTTP/1.1 中引入,用于指定缓存策略,优先于 Expires。 max-age=<seconds> 资源在缓存中保持“新鲜”的最长时间 1。
no-cache 缓存资源,但在使用前必须与源服务器进行验证 1。
no-store 禁止任何形式的缓存,通常用于敏感数据 1。
public 资源可由任何缓存(包括代理)缓存 1。
private 资源仅可由客户端浏览器缓存,不被共享缓存缓存(例如用户特定数据) 1。
must-revalidate 缓存过期后必须重新验证 1。
Expires 响应 HTTP/1.0 中引入,指定资源过期的固定日期和时间 1。 Expires: <date/time> 资源过期的时间戳 3。
ETag 响应 资源的特定版本标识符,用于协商缓存。 ETag: "<token>" 唯一标识资源版本的字符串,资源修改时会生成新 ETag 1。
Last-Modified 响应 资源的最后修改日期,用于协商缓存。 Last-Modified: <date/time> 资源最后被修改的时间 2。
Vary 响应 确定哪些请求头部必须与缓存资源匹配才能被视为有效。 Vary: <header-name> 例如 Vary: Accept-Language, User-Agent 3。

2. 浏览器缓存的演进:从共享到分区

浏览器缓存模型在过去二十多年中为网络服务提供了良好的支持。然而,为了加强用户隐私,它最近经历了一次根本性的转变,挑战了许多既有的性能优化假设。

2.1 传统模型:跨站资源共享

在过去,浏览器通常根据资源的来源(origin,即协议、域名和端口)来键控客户端状态,包括 Cookie、LocalStorage 对象和缓存 6。这意味着,无论资源是作为第一方资源加载,还是作为嵌入式第三方资源加载,其缓存都由该资源的来源域名共享。例如,如果

a.com 和 b.com 都加载了来自 share.com 的同一个 JavaScript 文件 share.com/a.js,那么当 a.com 首次加载并缓存该文件后,b.com 在后续访问时可以直接从浏览器缓存中获取该文件,而无需再次从 share.com 服务器下载。

这种传统模型带来了显著的优势,包括:通过跨站资源共享减少带宽使用,为访问多个使用共同资源站点的用户提供更好的性能,通过利用公共 CDN 降低托管成本,以及通过缓存命中实现更快的页面加载 7。这种共享机制在提高网络效率方面发挥了关键作用。

2.2 转向缓存分区:隐私与安全的必然要求

现代浏览器已从传统的共享缓存模型转向一种称为“状态分区”或“双键缓存”的新范式 6。这意味着,数据不再仅仅根据其来源(origin)进行存储,而是被隔离,并且仅在共享相同来源和相同顶级站点的上下文中可用 6。

这一根本性转变的驱动力主要源于日益增长的用户隐私和安全需求。传统共享缓存模型被发现存在多种可被滥用的漏洞,例如:网站 A 可以通过检查缓存中是否存在来自网站 B 的资源来探测用户的浏览历史,这是一种侧信道攻击 7。通过测量资源加载时间,攻击者可以利用计时攻击来推断缓存状态,进一步揭示用户行为 7。此外,共享缓存还被用于存储跨站超级Cookie作为指纹识别机制,这使得用户难以清除这些持久性标识符,除非清除整个缓存 7。一些概念验证的跨站搜索攻击也利用了缓存的特性,通过检查特定图片是否被缓存来检测用户搜索结果中的任意字符串 9。对于 Service Worker API,当从第三方上下文注册时,也存在通过历史嗅探进行跨站信息泄露的潜在风险,因此也对其进行了分区处理 8。为了应对这些威胁,Chrome 引入了“祖先位”到存储分区键中,以防止 iframe 在跨站嵌入时被错误地视为“第一方”,从而避免潜在的安全风险 8。

在具体实现上,HTTP 缓存现在使用顶级框架来源(可能还包括子框架来源)进行分区 9。这意味着,每个嵌入式资源都会为每个顶级网站分配一个独立的存储桶 6。主流浏览器已逐步采纳这一策略:Firefox 从 85 版本开始默认启用网络分区,从 103 版本开始默认启用动态分区(状态分区)6;Chrome 从 115 版本开始为所有用户启用存储分区 8,并计划从 2025 年 5 月 27 日发布的 Chrome 137 版本开始对 Blob URL 进行分区 8;Safari 也已对其缓存进行了分区 9。浏览器供应商普遍希望避免提供缓存分区的选择退出机制,因为这会保留隐私风险,并且这些风险有时难以完全理解和规避 9。

值得注意的是,这种向缓存分区的转变被明确描述为对许多性能优化假设的“根本性挑战” 7,并且是为增强安全和隐私保护而“接受的权衡” 7。这突显了网络开发中的一个核心矛盾:在一个方面(隐私和安全)的改进,往往会以牺牲另一方面(性能)为代价。相关资料表明,浏览器供应商正在优先考虑用户隐私和安全,即使这意味着整体缓存命中率略有下降 9和带宽消耗的增加 7。这是当前网络发展中一个重要的潜在趋势。

此外,对攻击向量的详细解释,如缓存探测、计时攻击、超级 Cookie、跨站搜索攻击和历史嗅探 7,揭示了缓存分区并非任意的改变,而是对恶意行为者如何利用先前共享的缓存模型进行跨站追踪和信息泄露的直接回应。主流浏览器(Safari、Firefox、Chrome)普遍采纳这一策略,且不提供选择退出机制 9,这表明浏览器供应商采取了统一的、积极主动的立场,从根本上重新设计网络的隐私架构,超越了被动修补。这预示着更广泛的行业趋势,即默认采用更严格的隐私设置。


表 1: 浏览器缓存的演进:共享与分区行为对比

特征 传统共享缓存模型 现代缓存分区模型
缓存键 主要基于资源来源 (e.g., share.com/a.js 的缓存键为 share.com) 6。 基于资源来源 顶级站点 (e.g., a.com 加载 share.com/a.js 的缓存键为 (a.com, share.com)) 6。
资源复用 跨站复用:a.com 缓存的 share.com/a.js 可被 b.com 直接复用。 限制跨站复用:a.com 缓存的 share.com/a.js 不能 被 b.com 直接复用 6。
性能影响 高缓存命中率,降低带宽,加速跨站资源加载 7。 缓存命中率降低(初步实验显示约 4%),增加带宽消耗,重复下载相同资源 7。
隐私/安全 存在跨站追踪、侧信道攻击、计时攻击、超级 Cookie 等漏洞 7。 显著增强用户隐私,防止多种形式的跨站追踪和攻击 6。
主要驱动 性能优化,减少网络请求。 隐私保护与安全强化。
浏览器支持 所有旧版浏览器。 Firefox 85+ (网络分区), 103+ (动态分区) 6;Chrome 115+ (存储分区) 8;Safari 已实现 9。

3. 缓存分区对外部 JavaScript 文件的影响

缓存分区机制的引入,对外部 JavaScript 文件的处理方式产生了直接且深远的影响,这直接关系到用户最初的疑问。

3.1 对用户查询的直接回答

针对用户提出的问题:“如果 a.com 和 b.com 都加载了 share.com/a.js,后访问的那个域名能不能因为共用了 share.com/a.js 得到受益?”

答案是:不能。 在现代浏览器中,后访问的域名 b.com 通常不会因为 share.com/a.js 已被 a.com 缓存而获得性能上的直接受益 6。这是因为每个顶级站点(例如

a.com 和 b.com)现在都为第三方资源(如 share.com/a.js)维护着自己独立的、隔离的缓存副本 6。缓存的键现在包含了顶级站点的来源信息 6,这意味着即使是完全相同的 JavaScript 文件,如果它们是由不同的顶级域名加载的,它们也会被视为不同的缓存条目。

3.2 性能权衡与资源重复

缓存分区虽然在隐私保护方面取得了显著进步,但不可避免地引入了性能上的权衡,尤其体现在资源重复下载方面。初步实验数据显示,这种机制可能导致整体缓存命中率下降约 4% 9。

这种命中率的下降直接转化为带宽消耗的增加和资源重复下载。例如,像 jQuery 或 React 这样的流行 JavaScript 库,过去可以受益于跨站缓存,现在则需要为每个加载它们的顶级站点单独下载 7。这意味着,即使这些框架由 CDN 托管,其在浏览器层面的跨站缓存优势也大幅降低 7。同样,来自 Google Fonts 等服务的常用网络字体也需要进行多次下载 7。这些重复下载的累积效应导致了整体带宽使用量的增加 7。

尽管存在这些性能影响,但浏览器供应商普遍认为这些是增强安全和隐私保护所必需且可接受的权衡 7。这种观点表明,网络生态系统正在重新校准其优先级,将用户隐私置于纯粹的性能指标之上。

传统上,内容分发网络(CDN)在广泛使用的第三方库分发中非常有效,因为它们能够利用跨站浏览器缓存,从而减少源服务器负载并提升跨多个站点的用户性能。随着缓存分区的实施,CDN 在浏览器层面提供共享缓存命中带来的“公共 CDN”优势显著减弱 7。虽然 CDN 仍然通过地理位置接近性提供优势并减少源服务器负载,但其在

浏览器级别跨站缓存效率方面的作用已发生根本性改变。这表明 CDN 提供商和网络开发者需要重新评估其价值主张和优化策略。

“接受的权衡”这一反复出现的主题 7,以及对隐私和安全的强调 6,表明在以隐私为先的网络环境中,传统的性能指标(例如,原始缓存命中率)可能需要重新评估。过去被视为“优化”的跨站缓存,现在被视为“安全漏洞”。这预示着未来的网络开发和性能工程将越来越注重速度与隐私之间的平衡,这可能导致新的度量标准出现,或者对现有度量标准进行重新排序。

4. 除 HTTP 缓存之外受影响的网络 API 和存储机制

缓存分区并非仅仅局限于 HTTP 缓存。它是一项“广泛的努力” 6,影响了第三方上下文中大多数存储和通信 API 8。这表明浏览器正在进行一项全面的系统级重构,以确保所有潜在的跨站追踪侧信道都被消除。

4.1 存储 API

  • 配额系统: 用于确定存储空间分配的配额系统现在将每个分区作为一个独立的存储桶进行管理,以控制空间限制和清除 8。
    navigator.storage.estimate() 方法现在提供特定于分区的信息 8。IndexedDB 和 Cache Storage 都利用了这种分区配额系统 8。
  • Web Storage API: 包括 Local Storage 和 Session Storage,它们提供浏览器存储键值对的机制。虽然它们不受配额管理,但仍然是分区的 8。
  • Origin Private File System: 作为 File System Access API 的一部分,此系统允许源将私有内容直接存储到磁盘。这些内容虽然用户可访问,但现在是分区的 8。
  • Storage Bucket API: 正在为 Storage Standard 开发,它通过引入“桶”的新概念来整合各种存储 API,如 IndexedDB 和 localStorage。存储在桶中的数据和与桶相关的元数据都是分区的 8。
  • Clear-Site-Data 头部: 服务器用于请求清除浏览器存储数据(缓存、Cookie、DOM 存储)的此头部,现在仅清除单个分区内的存储 8。
  • Blob URL 存储: 从 Chrome 137 版本(2025 年 5 月 27 日发布)开始,Blob URL 将为除顶级导航之外的所有用途进行分区 8。这意味着与
    fetch() 或作为 HTML 元素 src 属性一起使用的跨分区 Blob URL 将被阻止 8。

4.2 通信 API

这些 API 允许跨源通信,也同样被分区,主要影响那些通过广播或同源汇合发现其他上下文的 API。这防止了第三方 iframe 与其同源上下文交换数据 8。

  • Broadcast Channel: 允许浏览上下文(窗口、标签页或 iframe)和同源 Worker 之间进行通信 8。
  • SharedWorker: 提供一个可在同源浏览上下文之间访问的 Worker 8。
  • Web Locks: 允许在同源的某个标签页或 Worker 中运行的代码在执行某些工作时获取共享资源的锁 8。

4.3 Service Worker API

Service Worker 允许站点执行后台任务并与其同源上下文通信,当从第三方上下文注册时,它们现在也是分区的 8。这是因为它们存在跨站信息泄露的潜力,例如通过历史嗅探 8。

4.4 扩展 API

扩展页面(chrome-extension:// 方案)嵌入到网页中时,将继续访问其顶级分区 8。当扩展程序嵌入其他站点时,如果扩展程序具有这些站点的主机权限,则这些嵌入站点将访问其顶级分区 8。

上述受影响 API 的广泛列表表明,缓存分区并非对 HTTP 缓存的孤立改变,而是浏览器管理所有客户端状态和上下文间通信方式的更广泛、系统性重构的一部分。这表明,浏览器采取了一项全面的策略,旨在消除所有可能用于跨站追踪的侧信道,其范围远超仅仅处理 Cookie。这意味着开发者必须重新思考任何依赖于不同顶级上下文之间共享状态的模式,无论使用何种特定 API。

此外,像 SharedWorker 和 Broadcast Channel 等 API 的分区 8 意味着复杂的网络应用程序,特别是那些使用微前端或涉及第三方上下文的复杂跨标签页/跨 Worker 通信模式的应用程序,将需要进行重大的架构调整。这不仅仅关乎性能,更是关于基本功能的变化。它迫使开发者将顶级来源视为主要的安全边界,这可能会使过去依赖于不同嵌入上下文之间同源访问的共享状态管理模式变得复杂。


表 3: 浏览器缓存分区:受影响的 API 及其影响

API 类别 受影响的 API/机制 影响描述
存储 API 配额系统 (IndexedDB, Cache Storage) 每个分区被视为独立的存储桶,配额管理和清除均独立进行 8。
Web Storage API (Local Storage, Session Storage) 即使不受配额管理,也按顶级站点进行分区 8。
Origin Private File System 存储内容按顶级站点分区 8。
Storage Bucket API (开发中) 桶中数据和元数据均按分区处理 8。
Clear-Site-Data 头部 仅清除单个分区内的存储数据 8。
Blob URL 存储 从 Chrome 137+ 开始,除顶级导航外,Blob URL 均被分区 8。
通信 API Broadcast Channel 阻止第三方 iframe 与其同源上下文交换数据 8。
SharedWorker 阻止第三方 iframe 与其同源上下文交换数据 8。
Web Locks 阻止第三方 iframe 与其同源上下文交换数据 8。
Service Worker API Service Workers 当从第三方上下文注册时,Service Worker 被分区,以防止跨站信息泄露 8。
扩展 API 扩展页面嵌入网站 扩展页面访问其顶级分区;嵌入的网站访问其顶级分区(需主机权限) 8。

5. 适应分区缓存环境:给开发者的建议

面对浏览器缓存机制的根本性转变,网络开发者需要调整其策略,以适应新的隐私优先环境,同时尽可能地优化性能。

5.1 重新思考打包与代码分割

过去,开发者可能会倾向于创建大型的共享 JavaScript 包,以期通过跨站缓存来提高效率。但在分区缓存模型下,这种策略的收益大打折扣。现在,更小、更集中的代码包可能更为可取 7。代码分割的边界应与域名边界对齐 7,这意味着应将特定于某个顶级域名的代码与通用代码分离,以最大程度地减少重复下载大型共享块的影响。

5.2 战略性使用资源提示

尽管缓存分区限制了跨站共享,但开发者仍可利用资源提示(Resource Hints)来缓解性能影响。preconnect 可以提前建立与关键第三方域名的连接,dns-prefetch 可以预解析域名,而 preload 和 prefetch 则可以预先下载关键资源。虽然这些技术并非直接解决缓存分区问题,但它们能通过提前网络操作来弥补部分因重复下载而增加的延迟。

5.3 有效利用 HTTP 缓存头部(在分区内部)

即使在分区环境中,HTTP 缓存头部对于管理每个顶级站点内部的缓存仍然至关重要 1。开发者应继续利用

Cache-Control: max-age 来实现强缓存策略 1,并实现

ETag 和 Last-Modified 以支持协商缓存,从而在资源未更改时避免完整下载 1。此外,正确使用

public 和 private 指令对于确保内容在适当的缓存层级(例如,用户特定数据仅在客户端浏览器缓存)中存储至关重要 1。理解

no-cache 和 no-store 之间的区别,并根据数据的敏感性和变化频率进行选择,也是优化缓存行为的关键 1。

5.4 建立强大的性能监控机制

在新的缓存格局下,持续的性能监控变得尤为重要。开发者需要密切跟踪实际的页面加载时间、带宽消耗和缓存命中率,以评估缓存分区带来的真实影响 7。Chrome 开发者工具和 Firefox Web 控制台等工具可以帮助测试和验证缓存规则的有效性 1。

5.5 考虑应用层面的缓存

对于在不同来源之间访问的大型资源,如机器学习模型,开发者可能需要考虑在应用程序层面实施缓存策略 7。虽然 Service Worker 本身也受到分区的影响,但它们仍然可以在其特定的分区内管理缓存,为离线访问和更精细的资源控制提供可能 8。

5.6 未来展望

网络平台仍在不断演进,未来可能会探索新的解决方案,以在保护隐私的同时,实现“知名”大型资源的更好跨源缓存 7。这可能涉及新的 API 或模式,以在隐私和性能之间找到更优的平衡点。

过去,开发者可以相对被动地从常用库的跨站缓存中受益。现在,随着分区的实施,开发者需要更主动地管理每个顶级站点的资源加载和缓存。这要求对资产交付采取更深思熟虑和更细粒度的方法,从对共享资源的“一劳永逸”心态转向为每个不同上下文优化代码包和使用资源提示的更积极策略。

相关资料中明确指出,“解决方案不是对抗这些变化,而是相应地调整我们的架构和优化策略。网络平台将继续发展,新的 API 和模式将出现,以帮助平衡隐私与性能。” 7 这揭示了浏览器标准演进与网络开发实践之间共生关系。浏览器行为的变化(如分区)直接要求应用程序的构建和优化方式随之改变。这强调了网络开发是一个持续适应的过程,由不断发展的平台能力和优先级所驱动。

6. 结论

浏览器缓存外部 JavaScript 文件的方式已发生根本性转变。为了应对日益增长的隐私和安全威胁,现代浏览器普遍采用了缓存分区(或双键缓存)机制。这意味着,即使 a.com 和 b.com 都加载了 share.com/a.js,它们现在也会在各自独立的缓存分区中存储该文件,从而无法再从跨站共享缓存中获得性能收益。

这一转变是浏览器供应商在用户隐私和网络安全方面做出的战略性选择,尽管它以牺牲部分性能(如缓存命中率下降和带宽消耗增加)为代价。这种权衡不仅影响了 HTTP 缓存本身,还扩展到多种 Web API 和存储机制,要求开发者重新评估其应用程序架构和优化策略。

未来的网络开发将更加注重在隐私保护的前提下实现性能优化。开发者需要通过调整代码打包策略、有效利用现有缓存头部、实施强大的性能监控以及探索应用层面的缓存方案来积极适应这一新格局。随着网络平台的持续演进,可以预期将出现更多创新方案,以在隐私和性能之间寻求更佳的平衡。

引用的著作

  1. Browser Caching Explained: How to Make Your WordPress Site Load Instantly - Pressidium, 访问时间为 七月 9, 2025, https://pressidium.com/blog/browser-cache-work/
  2. Understanding HTTP Caching: Strong and Negotiated Cache | by Leapcell - Medium, 访问时间为 七月 9, 2025, https://leapcell.medium.com/understanding-http-caching-strong-and-negotiated-cache-54dc521e2def
  3. What is Cache-Control and How HTTP Cache Headers Work | CDN Guide - Imperva, 访问时间为 七月 9, 2025, https://www.imperva.com/learn/performance/cache-control/
  4. HTTP caching - MDN Web Docs, 访问时间为 七月 9, 2025, https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching
  5. Evolution of HTTP - MDN Web Docs, 访问时间为 七月 9, 2025, https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Evolution_of_HTTP
  6. State Partitioning - Privacy on the web | MDN, 访问时间为 七月 9, 2025, https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/State_Partitioning
  7. Double-keyed Caching: How Browser Cache Partitioning Changed the Web - Addy Osmani, 访问时间为 七月 9, 2025, https://addyosmani.com/blog/double-keyed-caching/
  8. Storage Partitioning | Privacy Sandbox, 访问时间为 七月 9, 2025, https://privacysandbox.google.com/cookies/storage-partitioning
  9. Intent to Implement: Partition the HTTP Cache, 访问时间为 七月 9, 2025, https://groups.google.com/a/chromium.org/g/blink-dev/c/6KKXv1PqPZ0/m/3_1nYzrBBAAJ