典型场景示例
- 新闻类应用:离线阅读已缓存文章,后台预拉取最新内容。
- 电商平台:弱网下展示商品缓存页,断网时暂存用户购物车操作。
- 协作工具:多设备间实时同步编辑内容,断网后自动提交未保存更改。
一、基本概念
Service Worker(SW)是运行在浏览器后台的独立线程,用于拦截网络请求、管理缓存资源及实现离线功能,是 PWA(渐进式 Web 应用)的核心技术。其特点包括:
- 无法直接操作 DOM,需通过
postMessage与主线程通信; - 必须运行在 HTTPS 或 localhost 环境;
- 生命周期独立于网页,可长期存活并处理后台任务
二、注册 Service Worker
通过 navigator.serviceWorker.register() 注册 SW 脚本,通常建议在页面加载完成后执行:
// 主线程代码
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js', { scope: '/' })
.then(registration => {
console.log('SW 注册成功:', registration.scope); // :ml-citation{ref="4,5" data="citationList"}
})
.catch(error => {
console.log('SW 注册失败:', error);
});
});
}
三、安装阶段(Install Event)
SW 首次注册或更新时会触发 install 事件,通常用于缓存核心静态资源:
// SW 线程代码 (sw.js)
self.addEventListener('install', event => {
event.waitUntil(
caches.open('my-cache-v1') // 创建/打开缓存空间
.then(cache => {
return cache.addAll([ // 缓存关键资源
'/',
'/styles.css',
'/app.js'
]);
})
);
}); // :ml-citation{ref="4,6" data="citationList"}
四、激活阶段(Activate Event)
当新 SW 准备就绪时触发 activate 事件,通常用于清理旧缓存:
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.filter(name => name !== 'my-cache-v1')
.map(name => caches.delete(name)) // 删除旧缓存
);
})
);
self.clients.claim(); // 立即控制所有页面:ml-citation{ref="5,7" data="citationList"}
});
五、拦截请求(Fetch Event)
SW 通过 fetch 事件拦截网络请求,实现缓存优先或网络优先策略:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request) // 检查缓存
.then(response => {
return response || fetch(event.request) // 返回缓存或发起网络请求
.then(res => {
return caches.open('my-cache-v1') // 动态缓存新资源
.then(cache => {
cache.put(event.request, res.clone());
return res;
});
});
})
); // :ml-citation{ref="1,5" data="citationList"}
});
六、通信机制
SW 与主线程通过 postMessage 和 message 事件通信:
// 主线程发送消息
navigator.serviceWorker.controller.postMessage({ type: 'UPDATE_DATA' });
// SW 监听消息
self.addEventListener('message', event => {
if (event.data.type === 'UPDATE_DATA') {
// 处理逻辑并回复
event.source.postMessage({ status: 'Updated' }); // :ml-citation{ref="2,5" data="citationList"}
}
});
七、生命周期注意事项
- 更新机制:SW 脚本内容变化时会触发更新,需通过
skipWaiting()强制激活新版本; - 调试工具:Chrome DevTools 的 Application > Service Workers 面板可查看状态及模拟离线环境。