CacheStorage API 实现离线缓存的核心是 Service Worker 预缓存关键资源并在 fetch 事件中主动匹配响应:先注册 SW,install 阶段用 caches.open().addAll() 预存静态资源,fetch 阶段用 caches.match() 优先返回缓存,未命中则回退网络或 offline 页面,版本更新时在 activate 阶段清理旧缓存。

使用 CacheStorage API 在离线状态下匹配并返回本地缓存,核心是:在 Service Worker 中预缓存关键资源,并在 fetch 事件中拦截请求、主动查缓存、命中则直接响应。它不依赖网络,完全由开发者控制缓存策略。
注册并激活 Service Worker
确保页面成功注册 Service Worker,这是所有缓存操作的前提:
- 在主页面的 JavaScript 中调用
navigator.serviceWorker.register('/sw.js') -
sw.js文件需与页面同源,且服务器返回Content-Type: text/javascript - 首次注册后,Service Worker 会经历
install → waiting → active流程;只有进入active状态后才能响应fetch事件
安装阶段预缓存静态资源
在 install 事件中打开缓存并添加初始资源(如 HTML、CSS、JS、图标等):
self.addEventListener('install', event => {
event.waitUntil(
caches.open('v1').then(cache =>
cache.addAll([
'/',
'/index.html',
'/styles.css',
'/app.js',
'/logo.png'
])
)
);
});
✅ 注意:cache.addAll() 是原子操作,任一文件失败将导致整个缓存失败;建议只放确定稳定、体积适中的关键资源。
拦截 fetch 请求并优先返回缓存
在 fetch 事件中检查请求是否命中缓存,命中则直接返回,否则尝试网络回退(或按需返回 fallback 页面):
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
// 缓存命中:直接返回
if (response) return response;
// 缓存未命中:发起网络请求
return fetch(event.request).catch(() => {
// 网络也失败(即离线)→ 可返回兜底页面
if (event.request.destination === 'document') {
return caches.match('/offline.html');
}
});
})
);
});
✅ 关键点:
-
caches.match()默认只匹配 URL 和 method,对 query 参数、headers 敏感;如需忽略参数,可用{ ignoreSearch: true } - 若想实现“网络优先但降级缓存”,可把
fetch()放前面,再用.catch()捕获失败后查缓存 - 动态资源(如 API 接口)通常不建议直接
addAll,可用“缓存-更新”策略(如 Stale-While-Revalidate)
更新缓存版本并清理旧缓存
发布新版本时,修改缓存名(如从 'v1' → 'v2'),并在 activate 阶段清理旧缓存:
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys =>
Promise.all(
keys.filter(key => key !== 'v2').map(key => caches.delete(key))
)
)
);
});
⚠️ 不清理旧缓存会导致磁盘占用持续增长,尤其在频繁迭代时。
不复杂但容易忽略的是:缓存匹配逻辑必须显式编写,浏览器不会自动为你离线服务;一切取决于你在 fetch 事件中如何决策——查缓存、发请求、还是合成响应。

















