Service Worker 入门
Service Worker 是一种相对较新的 API,近几年才被引入到现代网络浏览器中。这是一项非常重要的技术。它是一种特殊的网络工作器,可以安装在浏览器中,提供以前普通网页无法使用的特殊功能,例如允许离线访问网站内容。
服务工作者是渐进式 Web 应用程序的核心,因为它们允许缓存资源和推送通知,这是迄今为止使原生应用程序与众不同的两个主要特色。
属于渐进式 Web 应用Umbrella 主要致力于使用 Web 技术构建功能齐全的移动应用程序,与原生堆栈相比,这种体验并不低于标准。
Service Worker 在单独的线程上运行。这意味着您无法访问主 JavaScript 线程中可用的许多对象,包括对 DOM 和多个 API(如 XHR 或 Cookies)的访问。从好的方面来说,任何 Service Worker 操作都不会阻塞 UI 线程,因为它是完全独立的。
请记住,服务工作者需要通过 HTTPS 提供服务,否则浏览器将不会注册它们。
Service Worker 的主要特点
渐进式 Web 应用程序 (PWAs) 的最终目标是在移动设备上实现卓越性能,而 Web 在移动设备上始终失败的一件事就是处理离线状态。
服务工作者可以拦截网络请求,使用Cache API将它们添加到浏览器缓存中,并且如果检测到浏览器处于离线状态且网络不可用,它们就可以提供缓存资源。
另一个重要功能是通过使用Push API和Notifications API实现推送通知,这两个独立的 Web 平台 API 可供开发人员在服务工作线程中使用。
如何安装 Service Worker
服务工作者需要在浏览器中安装后才能使用。
首先,您需要检查浏览器是否实现了服务工作线程。
最好的方法是检查导航器对象serviceWorker
是否存在:
if (!('serviceWorker' in navigator)) {
// service workers not supported ????
return
}
如果有可用的服务工作线程,您可以通过指定服务工作线程所在的文件来注册服务工作线程。您始终会有一个单独的文件,可供浏览器访问。例如,您可以将其worker.js
放在根目录中的文件中。
等到页面加载完成后,使用以下命令注册服务工作navigator.serviceWorker.register()
线程:
window.addEventListener('load', () => {
if (!('serviceWorker' in navigator)) {
// service workers not supported ????
return
}
navigator.serviceWorker.register('/worker.js').then(
() => {
// registered! ????????
},
err => {
console.error('SW registration failed! ????', err)
}
)
})
Service Worker 生命周期
我提到过,服务工作线程需要在浏览器中安装才能使用。
当用户第一次访问你的网站时,服务工作者唯一能做的事情就是安装。
服务工作线程中的所有内容及其附带的任何功能,在用户访问您网站上的第二个页面或刷新当前页面之前都不会启用。这是设计使然。
Service Worker 中有什么
我们刚刚了解了如何安装位于worker.js
文件中的服务工作线程,但我们还没有研究该文件。
在服务工作线程中,你可以监听浏览器发出的几个事件:
fetch
每当您网站的页面需要网络资源时,都会发送此消息。它可以是新页面、JSON API、图像、CSS 文件等等。install
在安装服务工作者时发送。activate
在注册并安装服务工作线程后发送。如果服务工作线程已更新,您可以在此处清理与旧版本服务工作线程相关的任何内容。sync
如果浏览器先前检测到连接不可用,则会发送此消息,现在向服务工作者发出信号,表示互联网连接正在运行。push
当收到新的推送事件时由 Push API 调用。
提供缓存资源
安装服务工作线程后,我们可以告诉浏览器缓存稍后离线时为页面提供服务所需的特定资源:
self.addEventListener('install', event => {
event.waitUntil(
caches
.open('my-site-name')
.then(cache =>
cache.addAll([
'favicon.ico',
'style.css',
'script.js',
'https://fonts.googleapis.com/css?family=Inconsolata:400,700'
])
)
)
})
这段代码使用Cache API让浏览器将所有这些资源缓存在名为 的缓存中my-site-name
。
让我们看看如何监听fetch
事件,以便在用户下次访问我们网站的页面时向用户提供缓存资源:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
if (response) {
//we found an entry in the cache!
return response
}
return fetch(event.request)
})
)
})
我们检查缓存是否包含该request
属性所标识的资源,如果不包含,我们就启动获取请求来获取它。
self
还请注意上述示例中的用法。Workers 获得一个全局self
只读属性,以允许自己访问。
更新 Service Worker
一旦安装了服务工作线程,它将持续运行,直到被用户删除或您更新它。
要更新服务工作线程,您只需要在服务器中推送它的新版本(即使更改一个字节就足够了),浏览器就会检测到它是一个新版本,它将下载并安装它。
就像第一次安装时一样,新的服务工作线程直到下一个页面加载时才可用。