返回知识中心
身份

离线 Web 应用的 Cache Storage API

说明如何在离线 Web 应用中使用 Cache Storage API,并处理请求匹配、版本化发布、离线回退和清理。

文档中心

想直接进入 身份 文档吗?

这篇文章属于博客内容库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

Cache Storage API 为离线 Web 应用提供了一个可以命名的 Request 和 Response 存储。Service Worker 可以打开缓存、匹配请求,并在网络不可用时返回已保存的响应。API 不会替应用决定哪些资源可以长期保留、何时算新鲜,或哪个账号可以读取数据;这些都属于应用设计。

离线能力因此既是 Service Worker 问题,也是存储设计问题。可靠的设计要给每个缓存命名,在发布改变资源时进行版本化,为不同请求类别选择回退,并提供可预测的删除方式。Service Workers 规范定义了 worker 生命周期,MDN Cache 参考说明缓存方法和匹配行为。

流程图展示请求经过网络、版本化 Cache Storage、离线回退和用户清理

Cache Storage 负责什么

Service Worker 和在允许情况下的页面可以使用全局 CacheStorage 对象。caches.open('app-shell-v3') 创建或打开具名 Cache;cache.put(request, response) 保存响应;cache.match(request) 查找匹配项;caches.delete('app-shell-v2') 删除整个具名缓存。浏览器会把这些存储与 Web 源以及相关的浏览器配置文件或上下文关联起来。缓存名称是应用命名空间,不是同一源中不同代码之间的安全边界。

API 保存的是 Web 对象,而不是抽象的“离线模式”。响应可能是 HTML、JavaScript、CSS、图片或 JSON,也可能带有影响应用解释正文的响应头。只保存用途、生命周期和负责人都明确的响应。若响应包含会话令牌、账号数据或短期授权决定,应把它当作应用状态,而不是通用离线资源。

Cache Storage 与 HTTP 缓存、Cookie、localStorage、IndexedDB 和 Service Worker 注册信息彼此独立。清除一个存储不会自动清除其他存储。退出登录审查应列出应用使用的所有存储并逐项验证。cache.delete() 成功只能证明一个具名缓存消失,不能证明 Cookie 或 IndexedDB 记录也被删除。可参阅浏览器存储模型和存储分区隐私了解这些边界。

浏览器也可能在存储压力下逐出站点数据,用户还可以在浏览器设置中清除数据。逐出是空间管理的最后防线,不是发布流程或隐私控制。需要离线响应的应用必须能够重新获取它,并处理缓存为空的情况。多个功能共用同一源时,为缓存使用不同前缀,并写明谁可以删除每个前缀;清理例程不能因为名称不是当前版本就删除别的功能的数据。

避免意外的请求匹配

Cache.match() 按平台规定的 URL 和请求属性匹配已保存条目,不是对响应正文的通用数据库查询,也不是让每个方法都可以安全重放。应为请求分类并让 worker 策略保持可读。

带发布版本的 JavaScript、CSS 等静态资源适合 cache-first:先查版本化缓存,有条目就返回,没有条目再获取并写入同一缓存。导航文档或必须反映服务器状态的数据通常适合 network-first:先尝试网络,只有响应符合规则时更新缓存,网络失败才使用已保存响应。

不要无条件缓存每个成功响应。创建订单或修改资料的 POST 不会因为响应被写入 Cache Storage 就变得可以安全重复。被授权头、Cookie 或账号标识个性化的响应需要明确策略。很多应用最安全的离线行为是显示清楚的不可用状态并要求重新连接,而不是持久化响应。

查询参数、请求头、方法和缓存模式变化都可能改变匹配结果。如果表示形式随请求头变化,应把变化写入缓存键,或避免放入共享缓存。同一 URL 可以有多个合法表示形式,返回错误表示形式会造成正确性问题。设计文档应列出请求类别、缓存名称、新鲜度预期和回退方式。

导航回退要说明数据是否最新。worker 可以为导航请求返回缓存的应用外壳,但页面仍应显示离线状态、保留重试操作,不能把旧账号面板伪装成实时服务器响应。跨源资源和不透明响应也要单独审查允许的源、失败表现和删除方式,不要用 Cache Storage 检查或收集其他站点的私有内容。

版本化与发布更新

把缓存名称当成发布契约,例如 offline-shell-v7。在 install 阶段创建并填充新缓存,在 activate 阶段列出本功能拥有的名称并删除旧版本。新的 worker 可能在旧 worker 仍控制打开页面时处于 waiting 状态;可参考 MDN Service Worker 生命周期说明。

安装应从用户角度保持完整。如果关键资源下载失败,就拒绝安装,而不要激活缺少文件的缓存。可选资源可放入独立缓存并使用可重试路径。安装失败时保留旧 worker 通常比提供半成品发布更安全。

激活清理必须保守,只保留当前版本并删除本功能前缀下的旧名称。多个作用域的 worker 需要先明确所有权。发布记录应包含脚本版本、激活前后的缓存名称,以及是否观察到 waiting worker。

skipWaiting() 和 clients.claim() 会改变新 worker 开始服务页面的时间。它们可以缩短发布等待,但旧页面可能立即收到新脚本准备的响应。只有在新旧契约兼容并测试打开的标签页后才使用;不确定时让 worker 等待,并在明确的边界提示用户重新加载。资源 URL 也不应在不改变缓存名称的情况下悄悄替换;优先使用带内容哈希或发布版本的 URL。

离线回退与恢复

为外壳、导航、图片、字体、API 读取和写入操作分别定义结果。外壳可以从缓存渲染本地路由;API 旧记录需要显示时间和刷新控件;写入操作只有在幂等或具有应用级幂等键、并且有可见重试状态时才适合排队。Cache Storage 本身不提供持久写入队列或冲突解决。

网络失败时要区分缓存未命中与已缓存的错误。不要把临时 500 或登录跳转当作离线页面保存。写入缓存前检查状态和内容类型;回退不存在时返回简短的离线文档或受控错误响应,告诉用户下一步操作。

成功重试后,只有新响应通过与原响应相同的校验规则,才替换旧条目。离线编辑应保存在适合应用数据的存储中,并显示最近同步时间,不要把待写入内容藏在可能随发布删除的缓存条目里。测试冷启动、已有当前缓存和降级场景,记录 worker 状态、缓存名称、请求类别、响应来源、界面状态和恢复动作,不要把令牌或正文写入记录。

清理、退出登录与用户控制

删除是功能而不是杂务。为旧发布缓存提供命名操作,为账号或草稿数据提供独立操作,避免发布清理误删离线工作,也避免退出登录后仍留下账号数据。退出登录或切换账号时,先结束服务器会话,再让 worker 删除账号缓存,然后清理内存并通知其他标签页。两个标签页同时打开时必须测试,因为一个标签页可能继续显示旧缓存。

Clear-Site-Data 可以请求浏览器清除某些源数据,但指令覆盖范围随浏览器而异,不能替代应用清理。HTTP Cache-Control 只描述 HTTP 缓存行为,不会让 worker 自动跳过 cache.put()。真正写入 Cache Storage 的代码必须在保存前应用应用策略。

缓存设计也要遵循数据最小化:只存离线页面所需的最小响应,避免把访问令牌放进正文,为草稿和媒体设置明确保留规则。清理控件应说明会影响当前会话、排队工作还是静态资源,让共享设备用户无需打开开发者工具就能理解结果。

使用 BotBrowser 测试及边界

BotBrowser 支持创建具有隔离存储和会话状态的可重复浏览器上下文,团队可比较冷启动、暖缓存和退出登录流程,而不会把一个上下文的状态带入另一个上下文。可参考 多账号隔离文档,记录每个受控测试的 worker 状态、缓存名称和可见回退结果。BotBrowser 不能写入、版本化、清除或解释应用的 Cache Storage 条目,也不能保证浏览器逐出、离线可用性或 Service Worker 策略正确;缓存所有权和清理仍由应用负责。

可用的测试矩阵包括没有缓存的上下文、安装成功后的上下文和更新后的上下文。加载已知外壳,在测试环境允许的边界断开网络,确认回退明确标注离线;恢复连接后重试,并确认只有通过应用校验的新响应才会替换旧响应。使用两个上下文和两个标签页重复退出登录与切换账号检查,比较缓存名称和 worker 状态,不比较私有正文。

BotBrowser 证据应限于它能观察的行为:上下文隔离、导航结果、浏览器暴露的 worker 状态和应用自己的缓存列表断言。上下文比较通过不能证明所有浏览器逐出方式一致,也不能证明生产 Service Worker 正确或离线写入可安全重放;这些需要应用测试、浏览器覆盖和明确产品决策。

每个缓存名称都应说明用途和版本。

关键资源不完整时应拒绝安装。

可选资源应有独立的重试路径。

激活阶段只能删除本功能的前缀。

命中缓存不能证明请求使用了网络。

可见回退应说明何时可以重试。

账号响应不是外壳的公共资源。

两个标签页都应收到账号切换通知。

版本清理不应删除离线草稿。

测试记录不应包含令牌和私有正文。

公开来源

#Cache Storage#离线 Web 应用#Service Worker#浏览器存储

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。