良好的用户体验来自于反馈,我们在使用 web 时不希望看到下面的画面,即使在没有网或是网络不畅的情况下。

所以离线应用变得重要,有了离线应用,我们的 Web App在无网(offline)情况下可以访问,甚至使用部分功能,而不是展示“无网络连接”的错误页。

我们看一看 serviceWork 是如何帮助我们实现离线应用的。那么什么是 service Woker 呢?可以把 Service Worker 简单地理解为一个独立于前端项目,在后台运行的进程。因此,它不会阻塞浏览器脚本的运行,同时也无法直接访问浏览器相关的API(例如:DOM、localStorage等)。此外,即使在离开 Web App,甚至是关闭浏览器后,service work 仍然可以运行。来处理着缓存、推送、通知与同步等工作。所以,要学习PWA,绕不开的就是Service Worker。

这些部分会是PWA技术的重点。需要特别注意的是,由于Service Worker所具有的强大能力,因此规范规定,Service Worker 只能运行在 HTTPS 域下。然而我们开发时候没有 HTTPS 怎么办?别着急,还有一个贴心的地方——为方便本地开发,Service Worker 也可以运行在 localhost(127.0.0.1)域下

首先我们在项目的 index.html 同级目录下创建 sw.js。这个文件就是 serviceWorker。然后我们返回到 app.js 在 app.js 中注册 sw.js 文件。由于不是所有浏览器都支持。所以需要先判断是否支持serviceWorker。值得一提的是,Service Worker的各类操作都被设计为异步,用以避免一些长时间的阻塞操作。这些API都是以Promise的形式来调用的。

我们先测试测试一下 ,在 ws.js 中添加下面代码。

打开 console 看一下,我们

我们看一下 serviceWorker 做了哪些事情。其实 Service Worker 起了一个代理作用。Service Worker有一个非常重要的特性:你、可以在 Service Worker中监听所有客户端(Web)发出的请求,然后通过 Service Worker来代理,向后端服务发起请求。通过监听用户请求信息,Service Worker可以决定是否使用缓存来作为Web请求的返回


我们通过代码证明一下,客服端所有发起的请求都会被 fetch 这个监听器所监听。我们在 fetch 的监听器中打一个断点。

我们可以在 fetch 中返回 new Response("hello") 来代替所有客户端

我们可以通过下面代码来实现,当用户在客户端输入一个不存在的如有例如 http://localhost:5500/unknown.html。不会返回 404 页面,而是返回一个友好的页面。我们尝试使用 serviceWorker 来实现一下。我们通过判断返回的status 状态码如果为 404 那么就返回本地预先定义好 404.html 页面

看看效果。

好了,看一看如何使用Service Worker实现离线可用的“秒开”应用。

在开始之前我们需要储备一些有关 serviceWorker 的基础知识。

当我们注册了Service Worker后,它会经历生命周期的各个阶段,同时会触发相应的事件。整个生命周期包括了:installing --> installed --> activating --> activated --> redundant。当Service Worker安装(installed)完毕后,会触发install事件;而激活(activated)后,则会触发activate事件


我们在监听 install 事件,也就是说在 install 这个阶段做一些事,在回调函数中会获取 event 对象,我们用 event waitUntil 方法会接受一个 promise 对象。

caches.open 会返回一个 promise 对象。会创建一个缓存 static-v1 然后将一些静态资源缓存到这个 static-v1。然后我们在 fetch 监听器。

fetch 事件会监听所有浏览器的请求。event.respondWith() 方法接受 Promise 作为参数,通过它让Service Worker向浏览器返回数据。caches.match(event.request) 则可以查看当前的请求是否有一份本地缓存:如果有缓存,则直接向浏览器返回cache;否则Service Worker会向后端服务发起一个fetch(event.request)的请求,并将请求结果返回给浏览器。


我们可以在 cache 中查看到缓存内容。

然后勾选 offline 后会出现我们缓存的画面。


我们也可以更新缓存,内容提高一个版本为 static-v2 ,当我们更新却无法看到效果,我们需要关闭标签页,然后重新进入 web 才能看到效果如下。 

 serviceWorker 的威力不仅仅这些,随后我们继续会在其部分内容介绍 serviceWorker。