场景
一、离线支持
将网页的静态资源缓存下来,用户在离线状态下仍能访问网页。
二、消息推送
实现消息推送功能,即使用户未打开网页,也能接收到消息。
三、后台数据同步
在网络恢复后,后台同步数据,例如提交表单或保存状态。
四、资源缓存和管理
资源缓存和管理: 提高网页加载速度,通过缓存策略优化资源使用。在你的 service worker
注册之后,浏览器会尝试为你的页面或站点安装并激活它。install
事件会在注册成功完成之后触发。install
事件通常会这样用,将离线运行 app
产生的资源放置在浏览器离线缓存的空间。为了实现这个,我们使用了 Service Worker
的存储 API
——cache
—— 一个 service worker
上的全局对象,它使我们可以存储网络响应发来的资源,并且根据它们的请求来生成 key
。这个 API
和浏览器的标准的缓存工作原理很相似,但它特定于你的域的。直到你清理它们之前,这些内容都会持久存在。
-
新增了一个
install
事件监听器去监听service worker
(这里指的是self
),接着在事件上调用ExtendableEvent.waitUntil()
方法——这会确保Service Worker
不会在waitUntil()
里面的代码执行完毕之前安装完成。 -
在
addResourcesToCache()
内,我们使用了caches.open()
方法来创建了叫做v1
的新缓存,这将会是我们的站点资源缓存的第1
个版本。然后我们会在创建的缓存示例中调用addAll()
函数,它的参数采用一个URL
数组,指向你想要缓存的所有资源。其中,URL
是相对于worker
的location
4.1 创建 Service Worker
const addResourcesToCache = async (resources) => {
const cache = await caches.open("v1");
await cache.addAll(resources);
};
self.addEventListener("install", (event) => {
console.log('Service Worker 安装中...');
event.waitUntil(
addResourcesToCache([
"/",
"/index.html",
"/style.css",
"/app.js",
"/image-list.js",
"/star-wars-logo.jpg",
"/gallery/bountyHunters.jpg",
"/gallery/myLittleVader.jpg",
"/gallery/snowTroopers.jpg",
]),
);
});
self.addEventListener('activate', event => {
console.log('Service Worker 激活');
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.map(key => {
if (key !== 'v1') {
return caches.delete(key);
}
})
);
})
);
});
self.addEventListener('fetch', event => {
console.log('拦截请求:', event.request.url);
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
})
);
});
4.2 主线程注册 Service Worker
使用 ServiceWorkerContainer.register()
方法首次注册 service worker
。
const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register("/sw.js", {
scope: "/",
});
if (registration.installing) {
console.log("正在安装 Service worker");
} else if (registration.waiting) {
console.log("已安装 Service worker installed");
} else if (registration.active) {
console.log("激活 Service worker");
}
} catch (error) {
console.error(`注册失败:${error}`);
}
}
};
registerServiceWorker();
五、网络请求拦截与修改
网络请求拦截与修改: 拦截并修改网络请求,例如提供备用内容或处理失败的请求。
-
每次获取
service worker
控制的资源时,都会触发fetch
事件,这些资源包括了指定的作用域内的文档,和这些文档内引用的其他任何资源(比如index.html
发起了一个跨源的请求来嵌入一个图片,这个也会通过service worker
)。 -
你可以给
service worker
添加一个fetch
的事件监听器,接着调用event
上的respondWith()
方法来劫持我们的HTTP
响应,然后你用可以用自己的方法来更新它们。caches.match(event.request)
允许我们对网络请求里的每个资源与缓存里可获取的等效资源进行匹配,查看缓存中是否有相应的资源。该匹配通过URL
和各种标头进行,就像正常的HTTP
请求一样。
4.1 创建 Service Worker
const addResourcesToCache = async (resources) => {
const cache = await caches.open("v1");
await cache.addAll(resources);
};
self.addEventListener("install", (event) => {
console.log('Service Worker 安装中...');
event.waitUntil(
addResourcesToCache([
"/",
"/index.html",
"/style.css",
"/app.js",
"/image-list.js",
"/star-wars-logo.jpg",
"/gallery/bountyHunters.jpg",
"/gallery/myLittleVader.jpg",
"/gallery/snowTroopers.jpg",
]),
);
});
self.addEventListener('activate', event => {
console.log('Service Worker 激活');
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.map(key => {
if (key !== 'v1') {
return caches.delete(key);
}
})
);
})
);
});
self.addEventListener('fetch', event => {
console.log('拦截请求:', event.request.url);
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
})
);
});
4.2 主线程注册 Service Worker
使用 ServiceWorkerContainer.register()
方法首次注册 service worker
。
const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register("/sw.js", {
scope: "/",
});
if (registration.installing) {
console.log("正在安装 Service worker");
} else if (registration.waiting) {
console.log("已安装 Service worker installed");
} else if (registration.active) {
console.log("激活 Service worker");
}
} catch (error) {
console.error(`注册失败:${error}`);
}
}
};
registerServiceWorker();