Service Worker 实战:离线缓存与推送通知快速上手
什么是 Service Worker?
Service Worker 本质上是一个在浏览器后台运行的 JavaScript 脚本,它可以拦截网络请求、缓存资源、推送通知,即使在用户关闭网页后也能继续运行(部分功能)。这使得我们可以实现离线访问、消息推送等功能,极大地提升用户体验。
Service Worker 的生命周期
Service Worker 的生命周期包括:
- 注册(Register):在网页中注册 Service Worker。
- 安装(Install):Service Worker 首次安装时触发,通常用于缓存静态资源。
- 激活(Activate):Service Worker 安装完成后激活,可以清理旧的缓存。
- 运行(Running):Service Worker 拦截网络请求,处理推送通知等。
离线缓存实现
1. 注册 Service Worker
在你的 HTML 文件中,添加以下代码注册 Service Worker:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
console.log('Service Worker 注册成功,范围:', registration.scope);
})
.catch(function(error) {
console.log('Service Worker 注册失败:', error);
});
}
2. 创建 sw.js 文件
在你的网站根目录下创建一个名为 sw.js 的文件,用于编写 Service Worker 的逻辑。
3. 缓存静态资源
在 sw.js 文件中,监听 install 事件,缓存静态资源:
const CACHE_NAME = 'my-site-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/style.css',
'/script.js',
'/image.png'
];
self.addEventListener('install', function(event) {
// 执行安装步骤
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('已打开缓存');
return cache.addAll(urlsToCache);
})
);
});
4. 拦截网络请求并从缓存返回
监听 fetch 事件,拦截网络请求,如果缓存中存在对应的资源,则直接返回缓存中的资源:
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// 缓存命中 - 返回 response
if (response) {
return response;
}
// 未在缓存中找到 - 使用 fetch
return fetch(event.request);
}
)
);
});
5. 更新缓存
当网站资源更新时,我们需要更新缓存。监听 activate 事件,清理旧的缓存:
self.addEventListener('activate', function(event) {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
推送通知实现
1. 获取推送权限
在你的 JavaScript 代码中,请求用户授权推送通知:
function subscribePush() {
navigator.serviceWorker.ready.then(function(registration) {
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: 'YOUR_PUBLIC_VAPID_KEY' // 替换为你的 VAPID 公钥
})
.then(function(subscription) {
console.log('用户已订阅:', subscription);
// 将 subscription 发送到服务器
})
.catch(function(error) {
console.error('订阅失败:', error);
});
});
}
注意: 你需要生成一对 VAPID 密钥(公钥和私钥)用于安全地推送通知。可以使用在线工具或 Node.js 库生成。
2. 监听 push 事件
在 sw.js 文件中,监听 push 事件,当收到推送通知时显示通知:
self.addEventListener('push', function(event) {
const payload = event.data ? event.data.text() : '没有内容';
event.waitUntil(
self.registration.showNotification('推送通知', {
body: payload,
icon: '/icon.png'
})
);
});
3. 服务器端推送
你需要一个服务器端脚本来发送推送通知。使用 VAPID 私钥对请求进行签名,并将推送消息发送到 Google Cloud Messaging (GCM) 或 Firebase Cloud Messaging (FCM) 等推送服务。
示例总结
以上代码提供了一个简单的 Service Worker 实现离线缓存和推送通知的示例。你需要根据你的具体需求进行修改和扩展。例如,可以添加更复杂的缓存策略、处理不同类型的推送消息等。
注意事项
- HTTPS: Service Worker 只能在 HTTPS 环境下运行。
- 调试: 使用 Chrome 开发者工具的 Application 面板可以方便地调试 Service Worker。
- VAPID 密钥安全: 妥善保管你的 VAPID 私钥,不要泄露给他人。
希望这个简单的示例能帮助你快速上手 Service Worker,并将其应用到你的项目中!