什么是Service Worker?
Service Worker 是一种可编程的网络代理,是现代 Web 应用(PWA)不可或缺的一部分。它独立于网页运行,运行在单独的线程中,因此不会阻塞页面主线程。
注册(Register):通过navigator.serviceWorker.register()方法注册 Service Worker。如果注册成功,会返回一个ServiceWorkerRegistration对象,否则会抛出错误。
安装(Install):注册成功后,Service Worker进入安装阶段。这个阶段会触发install事件,开发者可以在这个阶段执行初始化操作,如缓存必要的资源。
激活(Activate):安装完成后,Service Worker 进入等待(waiting)状态。当所有旧版本的 Service Worker 控制的页面关闭后,或者通过self.skipWaiting()方法跳过等待阶段,Service Worker进入激活(activating)状态。这个阶段会触发activate事件,通常用于清理旧缓存和旧资源。
控制(Control):激活后,Service Worker 开始控制页面,并可以拦截网络请求。
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/service-worker.js')
.then(function (registration) {
console.log('Service Worker 注册成功,作用域:', registration.scope);
})
.catch(function (error) {
console.log('Service Worker 注册失败:', error);
});
});
}
service-worker.js
// 安装阶段
self.addEventListener('install', function (event) {
console.log('Service Worker 开始安装');
event.waitUntil(
caches.open('my - cache - v1')
.then(function (cache) {
return cache.addAll([
'/',
'/index.html'
]);
})
);
self.skipWaiting();
});
// 激活阶段
self.addEventListener('activate', function (event) {
console.log('Service Worker 开始激活');
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.filter(function (cacheName) {
// 过滤掉不需要的缓存
return cacheName.startsWith('my - cache -') && cacheName!== 'my - cache - v1';
}).map(function (cacheName) {
return caches.delete(cacheName);
})
);
})
);
self.clients.claim();
});
// 拦截请求阶段
self.addEventListener('fetch', function (event) {
console.log('Service Worker 拦截请求:', event.request.url);
event.respondWith(
caches.match(event.request)
.then(function (response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
Workbox 是 Google 推出的工具库,可以简化 Service Worker 的开发和配置。
npm install workbox-cli --save-dev
在项目根目录下生成 workbox-config.js 文件
npx workbox wizard
module.exports = {
globDirectory: './',
globPatterns: ['**/*.{html,js,css,png,svg}'],
swDest: 'sw.js',
runtimeCaching: [
{
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
handler: 'CacheFirst',
options: {
cacheName: 'images',
expiration: {
maxEntries: 10,
},
},
},
],
};
该命令会根据workbox-config.js中的配置生成一个sw.js文件(默认文件名),这就是你的 Service Worker 文件。
npx workbox generateSW workbox-config.js
在入口文件js处添加以下代码
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker注册成功', registration.scope);
})
.catch(err => {
console.log('Service Worker注册失败', err);
});
});
}
修改 Service Worker 文件,缓存 HTML、CSS、JS 和图片等静态资源。
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v1').then((cache) => {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/app.js',
'/logo.png'
]);
})
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
打开 Chrome DevTools(F12)。
切换到 Application 选项卡。
在 Service Workers 面板中,勾选 Offline。
刷新页面,检查是否能够正常加载。