Application Cache 不支持动态请求拦截或 Token 处理,仅静态映射资源;Service Worker + Cache API 可在 fetch 阶段拦截、改写或伪造响应,实现带 Token 接口的离线兜底。

HTML5 离线缓存本身(如 Application Cache)不支持动态请求拦截或 Token 处理,它只做静态资源映射,无法识别鉴权头、无法修改请求、也无法在离线时“模拟”带 Token 的接口响应。真正能解决这个问题的,是 Service Worker + Cache API 的组合方案——它允许你在 fetch 阶段主动拦截、判断、改写甚至伪造响应。
为什么 Application Cache 不行
Application Cache(.appcache)在 iOS 11.3+ 已基本禁用,且其机制是声明式预加载:清单里写什么,就缓存什么。它完全不感知 HTTP 请求头(比如 Authorization)、不执行 JS、不支持条件缓存或运行时逻辑。带 Token 的接口请求一旦离线,直接失败,无法 fallback 到 mock 数据或本地缓存结果。
Service Worker 如何拦截并处理带 Token 的请求
核心思路是:在 Service Worker 的 fetch 事件中,识别出需鉴权的 API 请求(如匹配 /api/ 路径),然后根据网络状态和缓存情况,决定是转发请求、返回缓存、还是返回预设的离线响应。
- 检查请求是否为鉴权接口:用
url.pathname.startsWith('/api/')或正则匹配关键路径 - 提取 Token(如果需要验证):可通过
event.request.headers.get('Authorization')读取,但注意离线时该头可能不存在或无效,此时不应阻断,而应进入兜底流程 - 优先尝试网络请求:用
fetch(event.request)发起真实调用;捕获TypeError(网络断开时抛出)作为离线信号 - 离线时 fallback 到缓存或 mock 响应:例如
cache.match('api-offline-fallback.json'),或直接构造new Response(JSON.stringify({...}), {headers: {'Content-Type': 'application/json'}}) - 避免缓存污染:对带 Token 的请求,建议使用
cacheKey = url.origin + url.pathname做缓存键,忽略 query 或 token 参数差异,防止缓存爆炸
Token 过期或缺失时的离线策略
离线状态下 Token 无法刷新,也不应尝试校验。重点不是“保持登录态”,而是“保障用户可继续操作”。可行做法:
立即学习“前端免费学习笔记(深入)”;
- 前端在发送请求前,若检测到
navigator.onLine === false,自动跳过 Token 添加逻辑,改用本地 mock 响应 - Service Worker 中对鉴权失败响应(如 401)不缓存,但可监听其返回,在主线程中触发登出提示
- 将关键业务数据(如表单草稿、待提交订单)存在 IndexedDB,等恢复在线后,用新 Token 补发请求并同步
- 骨架屏 HTML 中嵌入轻量 JS,监听
navigator.onLine变化,恢复连接后自动重试未完成的带 Token 请求
一个最小可行示例(worker.js)
在 install 阶段缓存离线响应文件:
caches.open('offline-v1').then(cache => {
cache.addAll([
'/offline-api-fallback.json', // 预置的{"code":0,"msg":"离线中","data":[]}
]);
});
在 fetch 中处理鉴权接口:
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
if (url.origin === location.origin && url.pathname.startsWith('/api/')) {
event.respondWith(
fetch(event.request)
.catch(() => caches.match('/offline-api-fallback.json'))
);
}
});
这个逻辑不依赖 Token 是否有效,也不校验请求头,纯粹以网络连通性为决策依据,兼顾安全性与离线可用性。



















