某某茶叶有限公司欢迎您!
金沙棋牌在线 > Web前端 > Service Worker 从入门到升级

Service Worker 从入门到升级

时间:2019-12-29 06:38

Service Worker入门

2015/03/26 · JavaScript · Service Worker

原文出处: Matt Gaunt   译文出处:[w3ctech

  • 十年踪迹]()   

原生App拥有Web应用通常所不具备的富离线体验,定时的静默更新,消息通知推送等功能。而新的Service workers标准让在Web App上拥有这些功能成为可能。

image

原文

简书放不了demo,demo可以看原文

Service Worker 是什么?

一个 service worker 是一段运行在浏览器后台进程里的脚本,它独立于当前页面,提供了那些不需要与web页面交互的功能在网页背后悄悄执行的能力。在将来,基于它可以实现消息推送,静默更新以及地理围栏等服务,但是目前它首先要具备的功能是拦截和处理网络请求,包括可编程的响应缓存管理。

为什么说这个API是一个非常棒的API呢?因为它使得开发者可以支持非常好的离线体验,它给予开发者完全控制离线数据的能力。

在service worker提出之前,另外一个提供开发者离线体验的API叫做App Cache。然而App Cache有些局限性,例如它可以很容易地解决单页应用的问题,但是在多页应用上会很麻烦,而Service workers的出现正是为了解决App Cache的痛点。

下面详细说一下service worker有哪些需要注意的地方:

  • 它是JavaScript Worker,所以它不能直接操作DOM。但是service worker可以通过postMessage与页面之间通信,把消息通知给页面,如果需要的话,让页面自己去操作DOM。
  • Service worker是一个可编程的网络代理,允许开发者控制页面上处理的网络请求。
  • 在不被使用的时候,它会自己终止,而当它再次被用到的时候,会被重新激活,所以你不能依赖于service worker的onfecth和onmessage的处理函数中的全局状态。如果你想要保存一些持久化的信息,你可以在service worker里使用IndexedDB API。
  • Service worker大量使用promise,所以如果你不了解什么是promise,那你需要先阅读这篇文章。

特别简的介

去年开始火遍南北的 PWA 技术落地情况有负重望,主要源于 safrai 对于这一技术支持不甚理想,不支持 mainfest 文件也不支持 service Worker

service worker 是一个特殊的 web Worker,因此他与页面通信和 worker 是一样的,同样不能访问 DOM。特殊在于他是由事件驱动的具有生命周期的 worker,并且可以拦截处理页面的网络请求(fetch),可以访问 cacheIndexDB

换言之 service Worker 可以让开发者自己控制管理缓存的内容以及版本,为离线弱网环境下的 web 的运行提供了可能,让 web 在体验上更加贴近 native。

前期准备

如下的基础知识:

  • Angular service workers介绍.

从5angular.0.0开始,在任意cli项目中,你可以很容易的开启Angular service worker。这文档是介绍怎么去在新的或旧的项目中启用Angular service worker。会通过一个简单的例子是展示service worker的行为与基本缓存。

Service Worker 是什么?

service worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本。
service worker不需要用户打开 web 页面,也不需要其他交互,异步地运行在一个完全独立的上下文环境,不会对主线程造成阻塞。基于service worker可以实现消息推送,静默更新以及地理围栏等服务。
service worker提供一种渐进增强的特性,使用特性检测来渐渐增强,不会在老旧的不支持 service workers 的浏览器中产生影响。可以通过service workers解决让应用程序能够离线工作,让存储数据在离线时使用的问题。

注意事项:
1.service worker运行在它们自己的完全独立异步的全局上下文中,也就是说它们有自己的容器。
2.service worker没有直接操作DOM的权限,但是可以通过postMessage方法来与Web页面通信,让页面操作DOM。
3.service worker是一个可编程的网络代理,允许开发者控制页面上处理的网络请求。
4.浏览器可能随时回收service worker,在不被使用的时候,它会自己终止,而当它再次被用到的时候,会被重新激活。
5.service worker的生命周期是由事件驱动的而不是通过Client。

Service Worker的生命周期

Service worker拥有一个完全独立于Web页面的生命周期。

要让一个service worker在你的网站上生效,你需要先在你的网页中注册它。注册一个service worker之后,浏览器会在后台默默启动一个service worker的安装过程。

在安装过程中,浏览器会加载并缓存一些静态资源。如果所有的文件被缓存成功,service worker就安装成功了。如果有任何文件加载或缓存失败,那么安装过程就会失败,service worker就不能被激活(也即没能安装成功)。如果发生这样的问题,别担心,它会在下次再尝试安装。

当安装完成后,service worker的下一步是激活,在这一阶段,你还可以升级一个service worker的版本,具体内容我们会在后面讲到。

在激活之后,service worker将接管所有在自己管辖域范围内的页面,但是如果一个页面是刚刚注册了service worker,那么它这一次不会被接管,到下一次加载页面的时候,service worker才会生效。

当service worker接管了页面之后,它可能有两种状态:要么被终止以节省内存,要么会处理fetch和message事件,这两个事件分别产生于一个网络请求出现或者页面上发送了一个消息。

下图是一个简化了的service worker初次安装的生命周期:

图片 1

兼容情况

safrai 已经于 2017年8月 开始了 service Worker 的开发。

image

目前浏览器PC支持情况如图

国内主要浏览器支持情况

android 设备在 4.4 版本使用 Chromium 作为内核,Chromium 在 40 对于 service worker 支持。国内浏览器包括微信浏览器在内基本已经支持 service Worker 这为提升体验提供了可能。service workerHTTP2 更加配哦,在将来基于它可以实现消息推送,静默更新以及地理围栏等服务。

在新项目中添加service worker

如果你要生成一个新的cli项目,你可以使用cli去配置Angular service worker:

ng new my-project --service-worker

--service-worker命令会去做所有的配置并添加需要依赖的包。想了解更多,可查看下面的关于如何在旧项目添加service worker的说明

Service Worker生命周期

service worker拥有一个完全独立于Web页面的生命周期

图片 2

sw-lifecycle.png

  1. 注册service worker,在网页上生效
  2. 安装成功,激活 或者 安装失败(下次加载会尝试重新安装)
  3. 激活后,在sw的作用域下作用所有的页面,首次控制sw不会生效,下次加载页面才会生效。
  4. sw作用页面后,处理fetch(网络请求)和message(页面消息)事件 或者 被终止(节省内存)。

在我们开始写码之前

从这个项目地址拿到chaches polyfill。

这个polyfill支持CacheStorate.match,Cache.add和Cache.addAll,而现在Chrome M40实现的Cache API还没有支持这些方法。

将dist/serviceworker-cache-polyfill.js放到你的网站中,在service worker中通过importScripts加载进来。被service worker加载的脚本文件会被自动缓存。

JavaScript

importScripts('serviceworker-cache-polyfill.js');

1
importScripts('serviceworker-cache-polyfill.js');

需要HTTPS

在开发阶段,你可以通过localhost使用service worker,但是一旦上线,就需要你的server支持HTTPS。

你可以通过service worker劫持连接,伪造和过滤响应,非常逆天。即使你可以约束自己不干坏事,也会有人想干坏事。所以为了防止别人使坏,你只能在HTTPS的网页上注册service workers,这样我们才可以防止加载service worker的时候不被坏人篡改。(因为service worker权限很大,所以要防止它本身被坏人篡改利用——译者注)

Github Pages正好是HTTPS的,所以它是一个理想的天然实验田。

如果你想要让你的server支持HTTPS,你需要为你的server获得一个TLS证书。不同的server安装方法不同,阅读帮助文档并通过Mozilla’s SSL config generator了解最佳实践。

了解前的了解

webWorker
fetch
cache
promise

在旧项目中添加service worker

添加步骤:

  1. 添加service worker的包依赖。
  2. 在cli配置中启用service worker。
  3. 导入和注册service worker。
  4. 新建配置文件,定义缓存的行为和其它设定。
  5. 编译项目。

Service Worker支持使用

使用Service Worker

现在我们有了polyfill,并且搞定了HTTPS,让我们看看究竟怎么用service worker。

生命周期

image

Service Workermain.js 进行注册,首次注册前会进行分析,判断加载的文件是否在域名下,协议是否为 HTTPS 的,通过这两点则成功注册。
service Worker 开始进入下一个生命周期状态 installinstall 完成后会触发 service Workerinstall 事件。 如果 install 成功则接下来是 activate状态, 然后这个 service worker 才能接管页面。当事件 active 事件执行完成之后,此时 service Worker 有两种状态,一种是 active,一种是 terminatedactive 是为了工作,terminated则为了节省内存。当新的 service Worker 处于 install/waitting 阶段,当前 service Worker 处于 terminated,就会发生交接替换。或者可以通过调用 self.skipWaiting() 方法跳过等待。
被替换掉的原有的 service WorkerRedundant 阶段,在 install 或者 activating 中断的也会进入 Redundant 阶段。所以一个 Service Worker 脚本的生命周期有这样一些阶段(从左往右):

[图片上传失败...(image-af3cfa-1511157771617)]

步骤1:添加service worker的包依赖。使用yarn包管理工具:

yarn add @angular/service-worker

浏览器支持

service worker support

图片 3

navigator-serviceworker.png

如何注册和安装service worker

要安装service worker,你需要在你的页面上注册它。这个步骤告诉浏览器你的service worker脚本在哪里。

JavaScript

if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js').then(function(registration) { // Registration was successful console.log('ServiceWorker registration successful with scope: ', registration.scope); }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }

1
2
3
4
5
6
7
8
9
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js').then(function(registration) {
    // Registration was successful
    console.log('ServiceWorker registration successful with scope: ',    registration.scope);
  }).catch(function(err) {
    // registration failed :(
    console.log('ServiceWorker registration failed: ', err);
  });
}

上面的代码检查service worker API是否可用,如果可用,service worker /sw.js 被注册。

如果这个service worker已经被注册过,浏览器会自动忽略上面的代码。

有一个需要特别说明的是service worker文件的路径,你一定注意到了在这个例子中,service worker文件被放在这个域的根目录下,这意味着service worker和网站同源。换句话说,这个service work将会收到这个域下的所有fetch事件。如果我将service worker文件注册为/example/sw.js,那么,service worker只能收到/example/路径下的fetch事件(例如: /example/page1/, /example/page2/)。

现在你可以到 chrome://inspect/#service-workers 检查service worker是否对你的网站启用了。

图片 4

当service worker第一版被实现的时候,你也可以在chrome://serviceworker-internals中查看,它很有用,通过它可以最直观地熟悉service worker的生命周期,不过这个功能很快就会被移到chrome://inspect/#service-workers中。

你会发现这个功能能够很方便地在一个模拟窗口中测试你的service worker,这样你可以关闭和重新打开它,而不会影响到你的新窗口。任何创建在模拟窗口中的注册服务和缓存在窗口被关闭时都将消失。

Install

install 存在中间态 installing 这个状态在 main.jsregistration注册对象中可以访问到。

/* In main.js */
// 重写 service worker 作用域到 ./
navigator.serviceWorker.register('./sw.js', {scope: './'}).then(function(registration) {  
    if (registration.installing) {
        // Service Worker is Installing
    }
})

安装时 service Workerinstall 事件被触发,这一般用于处理静态资源的缓存

service worker 缓存的静态资源

chrome PWA 演示实例

/* In sw.js */
self.addEventListener('install', function(event) {  
  event.waitUntil(
  // currentCacheName 对应调试工具中高亮位置,缓存的名称
  // 调用 `cache.open` 方法后才可以缓存文件
    caches.open(currentCacheName).then(function(cache) {
    // arrayOfFilesToCache 为存放缓存文件的数组
      return cache.addAll(arrayOfFilesToCache);
    })
  );
});

event.waitUntil() 方法接收一个 promise 对象, 如果这个 promise 对象 rejectedservice Worker 安装失败,状态变更为 Redundant。关于 cache 相关说明看下文。

步骤2:在cli配置中启用service worker:

要开启Angular service worker,cli必须在编译时生成Angular service worker的配置。要在旧项目中通知cli去做这一步,必须把.angular-cli.json文件里的 serviceWorker的值改成true

ng set apps.0.serviceWorker=true

polyfill

使用ServiceWorker cache polyfill让旧版本浏览器支持 ServiceWorker cache API,