Service Worker 与 PWA
概述
Service Worker 是 PWA 的核心,提供离线缓存、推送通知等能力。
一、生命周期
注册 → 安装 (install) → 激活 (activate) → 运行/空闲javascript
// 注册
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('Registered'))
.catch(err => console.error(err));
}
// sw.js
self.addEventListener('install', (e) => {
e.waitUntil(
caches.open('v1').then(cache => {
return cache.addAll(['/index.html', '/styles.css', '/app.js']);
})
);
self.skipWaiting(); // 立即激活
});
self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.filter(k => k !== 'v1').map(k => caches.delete(k))
);
})
);
self.clients.claim(); // 接管页面
});二、缓存策略
Cache First
javascript
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.match(e.request).then(cached => {
return cached || fetch(e.request);
})
);
});Network First
javascript
self.addEventListener('fetch', (e) => {
e.respondWith(
fetch(e.request).catch(() => caches.match(e.request))
);
});Stale-While-Revalidate
javascript
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.open('v1').then(cache => {
return cache.match(e.request).then(cached => {
const fetching = fetch(e.request).then(response => {
cache.put(e.request, response.clone());
return response;
});
return cached || fetching;
});
})
);
});三、PWA Manifest
json
{
"name": "My App",
"short_name": "App",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}html
<link rel="manifest" href="/manifest.json">四、推送通知
javascript
// 订阅
const reg = await navigator.serviceWorker.ready;
const subscription = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidPublicKey
});
// sw.js
self.addEventListener('push', (e) => {
const data = e.data.json();
e.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icon.png'
})
);
});面试高频题
Q1: Service Worker 的作用域?
默认是 sw.js 所在目录及子目录,可通过 scope 选项限制。
Q2: 更新 Service Worker 的策略?
新版本 install 后等待旧版本卸载,或使用 skipWaiting 立即激活。
Q3: PWA 安装条件?
HTTPS、有效的 manifest、注册的 Service Worker、满足安装提示条件。