Service Worker是一种运行在浏览器后台的脚本,主要功能包括提供离线支持、缓存资源、推送通知等。它是渐进式Web应用(PWA)的关键技术之一,旨在提高Web应用的性能和用户体验
1.使用场景和优势
Service Worker的主要用途包括:
- 离线缓存:可以缓存静态资源,使得应用在离线时也能访问。
- 网络请求拦截和处理:可以拦截并处理网络请求,例如伪造响应、转发请求等。
- 消息推送:可以向客户端推送消息。 执行耗时任务:如大量的数据运算。
- 执行耗时任务:如大量的数据运算。
2.创建serviceWorker.js
在public下新建文件:
const CACHE_VERSION = new Date().toISOString() // 或者一个静态版本号,比如 "v2"
const CACHE_NAME = `react-pwa-cache-${CACHE_VERSION}`
const urlsToCache = ["/", "/index.html", "/static/favicon.svg", "/manifest.json"]
// 安装阶段:预缓存关键静态资源
self.addEventListener("install", event => {
self.skipWaiting() // 跳过等待,立即激活新的 Service Worker
event.waitUntil(
caches.open(CACHE_NAME).then(cache => {
console.log("Opened cache")
return cache.addAll(urlsToCache)
})
)
})
// 抓取阶段:动态缓存新的请求资源
self.addEventListener("fetch", event => {
// 跳过 chrome-extension:// 请求
if (event.request.url.startsWith("chrome-extension://")) {
return
}
// 跳过非 GET 请求
if (event.request.method !== "GET") {
return
}
event.respondWith(
caches.match(event.request).then(cachedResponse => {
const fetchPromise = fetch(event.request).then(response => {
// 确保响应有效后缓存资源
if (!response || response.status !== 200 || response.type !== "basic") {
return response
}
// 更新缓存
const clonedResponse = response.clone()
caches.open(CACHE_NAME).then(cache => {
cache.put(event.request, clonedResponse)
})
return response
})
return cachedResponse || fetchPromise
})
)
})
// 激活阶段:清除旧缓存并立即启用新的 Service Worker。
self.addEventListener("activate", event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName) // 删除旧缓存
}
})
)
})
)
self.clients.claim() // 让新的 Service Worker 生效
})
//通过 message 事件来处理强制更新:
self.addEventListener("message", event => {
if (event.data === "SKIP_WAITING") {
self.skipWaiting()
}
})
3.注册Service Worker
在入口文件,启动函数里进行注册:
const SERVICEWORKER_URL = process.env.NODE_ENV === "production" ? "/serviceWorker.js" : "/serviceWorker.js"
console.log("环境变量:", process.env.NODE_ENV, SERVICEWORKER_URL)
// 注册 Service Worker
start(() => {
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register(SERVICEWORKER_URL)
.then(registration => {
console.log("ServiceWorker registration successful with scope: ", registration.scope)
// 如果有等待中的新的 Service Worker,发送 SKIP_WAITING 消息
if (registration.waiting) {
registration.waiting.postMessage("SKIP_WAITING")
}
// 监听 Service Worker 状态变化
registration.onupdatefound = () => {
const installingWorker = registration.installing
if (installingWorker) {
// 监听安装过程的状态变化
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed" && navigator.serviceWorker.controller) {
// 新的 Service Worker 安装完成并且页面已由旧的 Service Worker 控制
installingWorker.postMessage("SKIP_WAITING")
}
}
}
}
})
.catch(error => {
console.log("ServiceWorker registration failed: ", error)
})
})
}
})
4.webpack配置
const WorkboxWebpackPlugin = require("workbox-webpack-plugin")
// 在plugins插件中引入
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
navigateFallback: paths.publicUrlOrPath + "index.html",
navigateFallbackBlacklist: [
new RegExp("^/_"), // 排除以 /_ 开头的 URL
new RegExp("/[^/?]+\\.[^/]+$") // 排除资源文件
],
skipWaiting: true,
runtimeCaching: [
{
urlPattern: /\.(?:png|jpg|jpeg|svg|gif|css|js|html)$/,
handler: "CacheFirst",
options: {
cacheName: "assets-cache",
expiration: {
maxEntries: 50,
maxAgeSeconds: 1 * 24 * 60 * 60 // 缓存1天
}
}
},
{
urlPattern: /\/api\//,
handler: "NetworkFirst",
options: {
cacheName: "api-cache",
networkTimeoutSeconds: 10,
expiration: {
maxEntries: 10
}
}
}
]
}),
5.验证流程
查看缓存数据
- 打开开发者工具 >应用 >存储空间。
- 如需查看可用的缓存,请展开 Cache Storage。
- 查看缓存数据
点击缓存以查看其内容。
- 点击资源即可在表格下方的部分中查看其 HTTP 标头。
- 打开预览标签页以查看资源的内容。
刷新资源
- 查看缓存的数据。
- 选择要刷新的资源。开发者工具以蓝色突出显示 已选择。
点击 Refresh 刷新。
过滤资源
- 查看缓存的数据。
- 使用按路径过滤文本框,以过滤出与指定过滤器的路径不匹配的所有资源。
删除一项资源
- 查看缓存的数
- 点击要删除的资源。开发者工具会以蓝色突出显示它 已选择
删除所有缓存数据
- 打开应用 >存储空间。
- 在缓存部分,确保已启用 复选框。 缓存存储。
- 点击清除网站数据