Service Worker 的缓存机制是通过缓存 API 实现的,它允许开发者拦截和缓存 HTTP 请求,以提高离线体验和加速页面加载。以下是 Service Worker 缓存 HTTP 请求资源的基本流程和原理:
1. 注册 Service Worker
首先,Service Worker 需要在浏览器中注册。通常在主线程(如 JavaScript 入口文件)中进行注册:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
2. 安装 Service Worker
在 Service Worker 脚本中,首先会触发 install
事件。在这个事件中,可以预缓存一些资源,以便在 Service Worker 激活后立即可用:
self.addEventListener('install', event => {
event.waitUntil(
caches.open('my-cache-v1').then(cache => {
return cache.addAll([
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png'
]);
})
);
});
3. 激活 Service Worker
activate
事件在 Service Worker 安装完成后触发。可以在这个事件中进行缓存清理,删除旧的缓存:
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.filter(cacheName => {
// 这里可以指定要删除的缓存
return cacheName !== 'my-cache-v1';
}).map(cacheName => {
return caches.delete(cacheName);
})
);
})
);
});
4. 拦截和缓存请求
fetch
事件允许 Service Worker 拦截所有的网络请求。可以根据需要从缓存中返回资源,或将请求转发到网络:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
// 如果缓存中有匹配的资源,直接返回
if (cachedResponse) {
return cachedResponse;
}
// 否则,发起网络请求
return fetch(event.request).then(response => {
// 克隆响应对象,因为响应只能被消费一次
const responseClone = response.clone();
// 将网络请求的结果缓存
caches.open('my-cache-v1').then(cache => {
cache.put(event.request, responseClone);
});
return response;
});
}).catch(() => {
// 网络和缓存都失败的情况
return new Response('Oops, something went wrong.');
})
);
});
5. 资源管理
- 缓存清理:定期删除过期或不再需要的缓存,保持缓存的健康状态。
- 缓存策略:可以实现不同的缓存策略,如缓存优先、网络优先、缓存和网络同时等。