Service Worker 离线缓存原理
Service Worker 离线缓存原理
Service Worker 是一种运行在浏览器背后的独立线程,主要用于拦截网络请求、管理缓存以及实现离线访问功能。它是构建 PWA(Progressive Web App,渐进式 Web 应用)不可或缺的一部分。
下面我会详细讲解 Service Worker 离线缓存的原理,包括其工作流程、核心 API 及常见的缓存策略
一、基本原理
Service Worker 本质上是浏览器中的一个脚本,它可以拦截和处理网络请求,从而实现更灵活的资源管理。它运行在主线程之外,不影响页面性能。
离线缓存的核心思想是:
通过 Service Worker 拦截请求,优先从缓存中读取资源,如果没有再从网络请求,并将结果缓存,供下一次使用。
二、注册和生命周期
Service Worker 的生命周期包括以下几个阶段:
1. 注册(register)
在主线程中注册 Service Worker:
if ('serviceWorker' in navigator) {navigator.serviceWorker.register('/sw.js').then(reg => {console.log('Service Worker 注册成功', reg);}).catch(err => {console.error('注册失败:', err);});
}
2. 安装(install)
在安装阶段,通常会预缓存一些关键资源(App Shell):
self.addEventListener('install', event => {event.waitUntil(caches.open('my-cache-v1').then(cache => {return cache.addAll(['/','/index.html','/style.css','/main.js','/logo.png']);}));
});
caches 是 Cache API 提供的全局对象,可以创建和访问缓存
3. 激活(activate)
用于清理旧缓存:
self.addEventListener('activate', event => {const cacheWhitelist = ['my-cache-v1'];event.waitUntil(caches.keys().then(cacheNames => {return Promise.all(cacheNames.map(name => {if (!cacheWhitelist.includes(name)) {return caches.delete(name);}}));}));
});
三、拦截请求(fetch 事件)
Service Worker 拦截所有页面请求,可通过各种策略处理缓存:
self.addEventListener('fetch', event => {event.respondWith(caches.match(event.request).then(cachedRes => {// 有缓存就返回,否则请求并缓存return cachedRes || fetch(event.request).then(networkRes => {return caches.open('my-cache-v1').then(cache => {cache.put(event.request, networkRes.clone()); // 克隆一份放缓存return networkRes;});});}).catch(() => {// 如果请求失败(断网),返回默认离线页面return caches.match('/offline.html');}));
});
四、常见缓存策略
策略名称 | 描述 |
---|---|
Cache First | 优先使用缓存,没有则请求网络。适合静态资源(如图片、CSS) |
Network First | 优先请求网络,请求失败再使用缓存。适合内容频繁更新的页面 |
Stale-While-Revalidate | 使用缓存的同时异步更新缓存。结合体验与数据新鲜度 |
Cache Only | 只用缓存,不请求网络 |
Network Only | 只走网络,不用缓存(如登录接口) |
五、注意事项
-
Service Worker 只能运行在 HTTPS 或 localhost 下(出于安全考虑)
-
缓存更新时,必须修改缓存版本号,否则浏览器默认认为旧缓存仍然有效
-
注意缓存控制策略,避免缓存不一致或缓存污染。