关于 Service Worker 你想了解的一切
这篇博客主要讲解 Service Worker,包括它的工作原理、适用场景、移除方法、以及哪些场景下 Service Worker 无法正常工作等等。首先从简介开始。
服务工作者
服务工作者是作为后台进程在用户浏览器中运行的 Java 脚本文件。
Service Worker 的工作原理
它拦截网络请求,缓存或从缓存中检索资源,并传递推送消息。服务工作者可以被浏览器中的多个选项卡同时访问,因为每个范围只能存在一个服务工作者,并且存在与主线程无关。
要在你的项目中安装 Service Worker,首先你需要注册 Service Worker
注册服务工作者
要注册服务工作者,首先我们需要使用“navigator 对象”检查浏览器是否支持它。navigator 对象包含有关浏览器的信息。
当您调用 register() 函数时,您的第一个服务工作线程就会下载。
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/ServiceWorker.js')
.then(function(response) {
// Service worker registration done
console.log('Registration Successful', response);
}, function(error) {
// Service worker registration failed
console.log('Registration Failed', error);
})
}
Service Worker 只能访问其下级文件夹,因此最好将其保存在项目的根目录(最顶层文件夹)中。Service
Worker 上的 Register 函数会从提供的 URL 下载 Service Worker 脚本并执行。
在上面的代码响应中包含了有关服务工作者的状态及其范围的信息。
在 ServiceWorker.js 文件中我们可以编写安装、更新、推送等代码。
如果服务工作者注册失败,则注册承诺将被拒绝,并且服务工作者将被丢弃。
如何添加 Service Worker
成功注册service worker后,安装即可执行:
安装 Service Worker:
如果 Service Worker 是新版本或更新版本,则安装过程将启动。在此阶段,您可以缓存静态内容或文件。
此事件仅在“ServiceWorker.js”不存在或文件为较新版本(已更新)时触发。
self.addEventListener('install', cach => {
event.waitUntil(
caches.open('v1').then(cache => {
return cache.addAll([
'/favicon.ico',
]);
})
);
});
如果任何文件未能成功捕获(cache.addAll() 函数提供的捕获方式),则 Service Worker 未安装。
使用 event.waitUntil() 时,Service Worker 不会终止,直到传递给 waitUntil() 方法的 Promise 被解决或拒绝。
安装成功后触发Service Worker的激活事件
self.addEventListener('activate', event => {
console.log('v1 now ready to handle fetches');
})
如何清除 Service Worker 缓存
在激活事件中,我们可以使用 cache.delete() 方法移除或删除现有的缓存项目。
用于移除清除捕获
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
caches.delete(cacheName);
});
});
)
}
caches.keys() 方法提供所有您可以访问的缓存的名称。
每次用户请求页面时,Service Worker 都会触发 fetch 事件。
在此事件中,我们决定是否让该请求发送到网络或显示捕获的项目。
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
//serve the image from catch if the request is same origin
if(url.origin === location.origin) {
//image which is stored at the time of installation
//respond with cached
event.respondWith(caches.match('/favicon.ico'));
}
})
通过网络呼叫做出回应
self.addEventListener('fetch', event => {
event.respondWith(fetch(event.request));
})
respondWith() 方法允许您自己承诺做出回应。
更新 Service Worker
如果我们在服务工作者的脚本文件中进行更改,那么浏览器将被视为新的服务工作者,并且会安装事件触发。
当我们更新 Service Worker 时,新的 Service Worker 不再控制客户端,因为
旧的 Service Worker 负责处理客户端。当我们关闭浏览器时,旧的 Service Worker 会被终止,新的 Service Worker 会取代旧的 Service Worker。
如果我们想在安装完成后立即使用新的 Service Worker,可以使用 self.skipWaiting() 方法。
此方法会在 Service Worker 安装完成后激活它。
如果新的服务工作线程安装失败,旧的服务工作线程将继续处理客户端(页面)。
在开发模式下,选中重新加载时更新复选框,即在页面刷新时更新服务工作者。
调试 Service Worker
服务工作者仅适用于“安全来源”(基本上是 HTTPS 站点)。
要从 chrome 检查服务工作者,
请转到开发人员工具(F12)或右键单击页面,单击检查选项卡,
转到应用程序选项卡,然后单击侧边栏中的服务工作者,
在侧边栏中,您可以看到注册服务工作者的列表。
如何在本地主机上测试服务工作者
出于开发目的,您可以使用 localhost,因为 localhost 也被视为“安全来源”。或者,使用 npm http-server 和 serve 包搭建本地服务器。
取消注册服务工作者/删除服务工作者/禁用服务工作者
取消注册 Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistration().then(
function(registrations) {
for(let registration of registrations) {
registration.unregister();
}
}
)
}
Service Worker 可能不会立即终止。如果该 Worker 当前正在为客户端执行任何任务,它会在正式移除之前完成。只有在页面重新加载或关闭后,它才会被移除。
因此,您可以创建虚拟的新服务工作线程,并用它代替当前正在运行的服务工作线程。
通过将服务工作线程的 unregister() 方法放置在服务工作线程的激活事件中,强制每个客户端的浏览器重新加载页面。
如何从 Chrome 手动取消注册 Service Worker
转到开发人员工具(F12)或右键单击页面,单击检查选项卡,
转到应用程序选项卡,然后单击侧边栏中的服务工作者
在服务工作者中,您有已注册服务工作者的列表
,您可以通过单击取消注册链接手动取消注册服务工作者。