JavaScript是如何工做的:Service Worker的生命周期及使用场景

摘要: 理解Service Worker。javascript

Fundebug经受权转载,版权归原做者全部。前端

这是专门探索 JavaScript 及其所构建的组件的系列文章的第8篇。java

若是你错过了前面的章节,能够在这里找到它们:web

你可能已经知道,渐进式Web应用程序 只会愈来愈受欢迎,由于它们的目标是让Web应用程序用户体验更流畅,建立相似于原生应用程序的体验,而不是浏览器的外观和感受。编程

构建渐进式Web应用程序的主要要求之一是使其在网络和加载方面很是可靠——它应该在不肯定或不存在的网络条件下可用。小程序

在这篇文章中,将深刻探讨 Service Workers:它们是如何工做,你应该关心什么。最后,还列出了 Service Workers 中的一些独特优势在哪些场景下是值得咱们使用的。segmentfault

简介

若是你还想了解更多 Service Workers 的知识,能够阅读做者关于 Web Workers 的文章。微信小程序

Service Worker是什么数组

MDN 的介绍:promise

Service Worker 是一个浏览器背后运行的脚步,独立于 web 页面,为无需一个页面或用户交互的功能打开了大门。今日,它包含了推送通知和背景异步(push notifications and background sync)的功能。未来,Service Worker 将支持包括 periodic sync or geofencing 的功能。

基本上,Service Worker 是 Web Worker 的一个类型,更具体地说,它像 Shared Worker

  • Service Worker 在其本身的全局上下文中运行
  • 它没有绑定到特定的网页
  • 它不能访问到 DOM

这是一个使人兴奋的 API 的缘由是它容许你支持离线体验,让开发人员彻底控制体验。

Service Worker 的生命周期

Service Worker 的生命周期与 web 页面彻底分离。它包括如下几个阶段:

  • 下载
  • 安装
  • 激活

下载

这是浏览器下载包含 Service Worker 的 .js 文件的时候。

安装

要为 web 应用程序安装 Service Worker,必须先注册它,这能够在 JavaScript 代码中完成。注册 Service Worker 后,它会提示浏览器在后台启动 Service Worker 安装步骤。

经过注册 Service Worker,你能够告诉浏览器你的 Service Worker 的 JavaScript 文件的位置。看看下面的代码:

上例代码首先检查当前环境中是否支持 Service Worker API。若是支持,则 /sw.js 这个 Service Worker 就被注册了。

每次页面加载时均可以调用 register() 方法,浏览器会判断 Service Worker 是否已经注册,根据注册状况会对应的给出正确处理。

register() 方法的一个重要细节是 Service Worker 文件的位置。在本例中,能够看到 Service Worker 文件位于域的根目录,这意味着 Service Worker 范围将是这个域下的。换句话说,这个 Service Worker 将为这个域中的全部内容接收 fetch事件。若是咱们在 /example/sw.js 注册 Service Worker 文件,那么 Service Worker 只会看到以 /example/ 开头的页面的 fetch 事件(例如 /example/page1//example/page2/)。

一般在安装步骤中,你须要缓存一些静态资源。 若是全部文件都缓存成功,则 Service Worker 将被安装。 若是任何文件没法下载和缓存,则安装步骤将失败,Service Worker 将不会激活(即不会被安装)。 若是发生这种状况,不要担忧,下次再试一次。 可是,这意味着若是它安装,你知道你有这些静态资源在缓存中。

若是注册须要在加载事件以后发生,这就解答了你“注册是否须要在加载事件以后发生”的疑惑。这不是必要的,但绝对是推荐的。

为何?让咱们考虑用户第一次访问你的 Web 应用程序。目前尚未 Service Worker,并且浏览器没法预先知道最终是否会安装 Service Worker。若是安装了 Service Worker,浏览器将须要为这个额外的线程花费额外的 CPU 和内存,不然浏览器将把这些额外的 CPU 和内存用于呈现 Web 页面。

最重要的是,若是在页面上安装一个 Service Worker,就可能会有延迟加载和渲染的风险 —— 而不是尽快让你的用户可使用该页面。

注意,这种状况对第一次的访问页面时才会有。后续的页面访问不会受到 Service Worker 安装的影响。一旦 Service Worker 在第一次访问页面时被激活,它就能够处理加载/缓存事件,以便后续访问 Web 应用程序。这一切都是有意义的,由于它须要准备好处理受限的的网络链接。

激活

安装 Service Worker 以后,下一步将是激活它,这是处理旧缓存管理的好机会。

在激活步骤以后,Service Worker 将控制全部属于其范围的页面,尽管第一次注册 Service Worker 的页面将不会被控制,直到再次加载。

Service Worker 一旦掌控,它将处于如下两种状态之一:

  • 处理从网页发出网络请求或消息时发生的提取和消息事件
  • Service Worker 将被终止以节省内存

Service Worker 生命周期以下:

Service Worker 安装的内部机制

在页面启动注册过程以后,看看 Service Worker 脚本中发生了什么,它经过向 Service Worker 实例添加事件监听来处理 install 事件:

如下是处理安装事件时须要采起的步骤:

  • 开启一个缓存
  • 缓存咱们的文件
  • 确认是否缓存了全部必需的资源

对于最基本的示例,你须要为安装事件定义回调并决定要缓存哪些文件。

self.addEventListener('install', function(event) { // Perform install steps });

下面是 Service Worker 简单的一个内部安装过程:

从上例代码能够获得:

调用了caches.open() 和咱们想要的缓存名称, 以后调用 cache.addAll() 并传入文件数组。 这是一个promise 链( caches.open() 和 cache.addAll() )。 event.waitUntil() 方法接受一个承诺,并使用它来知道安装须要多长时间,以及它是否成功。

若是成功缓存了全部文件,那么将安装 Service Worker。若是其中的一个文件下载失败,那么安装步骤将失败。这意味着须要当心在安装步骤中决定要缓存的文件列表,定义一长串文件将增长一个文件可能没法缓存的机会,致使你的 Service Worker 没有获得安装。

处理 install 事件彻底是可选的,你能够避免它,在这种状况下,你不须要执行这里的任何步骤。

运行时缓存请求

安装了 Service Worker 后,用户导航到另外一个页面或刷新所在的页面,Service Worker 将收到 fetch 事件。下面是一个例子,演示如何返回缓存的资源或执行一个新的请求,而后缓存结果:

上述流程:

  • 在这里咱们定义了 fetch 事件,在 event.respondWith() 中,咱们传递了一个来自 caches.match()promise。 此方法查看请求,并查找来自 Service Worker 建立的任何缓存的任何缓存结果。
  • 若是在缓存中,响应内容就被恢复了。
  • 不然,将会执行 fetch。
  • 检查状态码是否是 200,同时检查响应类型是 basic,代表响应来自咱们最初的请求。在这种状况下,不会缓存对第三方资源的请求。
  • 响应被缓存下来

若是经过检查,克隆响应。这是由于响应是 Stream,因此只能消耗一次。既然要返回浏览器使用的响应,并将其传递给缓存使用,就须要克隆它,以即可以一个发送到浏览器,一个发送到缓存。

更新 Service Worker

当用户访问你的 Web 应用程序时,浏览器试图从新下载包含 Service Worker 代码的 .js 文件,这是在后台完成的。

若是如今下载的 Service Worker 的文件与当前 Service Worker 的文件相好比果有一个字节及以上的差别,浏览器将假设 Service Worker 文件已改过,浏览器就会启动新的 Service Worker。

新的 Service Worker 将启动而且安装事件将被移除。然而,在这一点上,旧的 Service Worker 仍在控制你的 web 应用的页面,这意味着新的 Service Worker 将进入 waiting 状态。

一旦你的 Web 应用程序当前打开的页面被关闭,旧的 Service Worker 将被浏览器杀死,新 Service Worker 接管了控制权,它的激活事件将被激发

为何须要这些?为了不 Web 应用程序的两个版本同时在不一样的 tab 上运行的问题——这在 Web 上是很是常见的,而且可能会产生很是严重的bug(例如,在浏览器中本地存储数据时使用不一样的模式)。

从缓存中删除数据

在激活回调中发生的一个常见任务是缓存管理。你要在激活回调中这样作的缘由是,若是你要在安装步骤中清除全部旧的缓存,任何保留全部当前页面的旧 Service Worker 将会忽然中止服务来自该缓存的文件。

这里提供了一个如何从缓存中删除一些不在白名单中的文件的例子(在本例中,有 page-一、page-2 两个实体):

要求 HTTPS 的缘由

在构建 Web 应用程序时,经过 localhost 使用 Service Workers,可是一旦将其部署到生产环境中,就须要准备好 HTTPS( 这是使用HTTPS 的最后一个缘由)。

使用 Service Worker,能够很容易被劫持链接并伪造响应。若是不使用 HTTPs,人的web应用程序就容易受到黑客的攻击。

为了更安全,你须要在经过 HTTPS 提供的页面上注册 Service Worker,以便知道浏览器接收的 Service Worker 在经过网络传输时未被修改。

浏览器支持

浏览器对 Service Worker 的支持正在变得愈来愈好:

Service Workers 特性将愈来愈完善及强大

Service Workers 提供的一些独特特性包括:

  • 推送通知 — 容许用户选择从网络应用程序及时更新。
  • 后台同步 — 容许延迟操做,直到用户具备稳定的链接。经过这种方式,能够确保用户想发送的任何内容实均可以发送。
  • 按期同步(后续开放) — 提供管理按期后台同步功能的 API。
  • Geofencing (后续开放) — 能够定义参数,也称为围绕感兴趣领域的 geofences。当设备经过geofence 时,Web 应用程序会收到一个通知,该通知容许根据用户的地理位置提供更好的体验。

原文:

https://blog.sessionstack.com...

代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。

你的点赞是我持续分享好东西的动力,欢迎点赞!

一个笨笨的码农,个人世界只能终身学习!

更多内容请关注公众号《大迁世界》!

关于Fundebug

Fundebug专一于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了9亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业。欢迎你们免费试用

相关文章
相关标签/搜索