Service worker

2018-10-15  本文已影响0人  Ching_Lee

1.Service worker是什么?

service worker的出现,是为了能够使web app拥有与native app或者本地应用程序相同的离线使用、消息推送、后台自动更新的能力。

service worker是一段脚本,浏览器独立于当前网页,将其在后台运行,它推出的第一个首要特性,就是拦截和处理网络请求的能力,包括以编程方式来管理被缓存的响应。

service worker可以:

1.后台消息传递
2.网络代理,转发请求,伪造响应
3.离线缓存
4.消息推送

关于 service worker 的注意:

2.Service worker的生命周期

通常遵循以下基本步骤来使用 service workers:

生命周期

1)注册

要安装service worker,您需要通过在页面中对其进行注册来启动安装。 这将告诉浏览器service worker 的JavaScript 文件的位置。

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/htmlcache.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);
  });
}

这里/htmlcache.js这个文件将会作为service worker被注册,如果这个 service worker 已经被注册过,浏览器会自动忽略上面的代码。

Service worker的作用域

一个 service worker 的默认作用域是这个 service worker 脚本所在的目录。
在上面例子中,service worker 文件被放在这个域的根目录下,这个 service worker 将会获取到这个域下的所有 fetch 事件。如果 service worker文件注册到/example/sw.js ,那么 service worker 只能收到 /example/ 路径下的 fetch 事件(比如: /example/page1/, /example/page2/)。

你也可以在注册 service worker 时明确指定作用域:

  navigator.serviceWorker.register("/htmlcache?bid=<%= bid %>", { scope: "/abc" })
        .then(function() {
            window._timePoints[29] = +new Date(); // 注册service worker 完成
        })
        .catch(function(err) {
            console.error("[Service worker] Install fail:" + err);
        });

假设以上代码在 https://example.com 页面里执行,则意味着该 service worker 的作用域就是 https://example.com/abc 下的页面。

2) installing安装中

在你所控制的页面上完成 service worker 的注册步骤之后,让我们把注意力转到 service worker 的脚本中,也就是register的第一个参数,我们要在其中完成它的安装。

在浏览器首次加载Service Worker或者Service Worker发生了更改后,Service Worker就会进入installing状态,并且触发install事件。这个时候,我们就可以为Web应用的启动进行一些初始化的工作,例如下载并缓存必要的资源文件,或者往indexedDB中填充数据,就和平时下载安装本地App时所做的工作一致。一旦完成准备工作,我们就可以通过调用event.waitUntil方法告知浏览器Service Worker已经安装完成了。

self.addEventListener("install", (event) => {
  console.log("Service Worker正在安装中");
  event.waitUntil(
   caches.open('v1').then(function(cache) {
      return cache.addAll([
        '/sw-test/',
        '/sw-test/index.html',
        '/sw-test/style.css',
        '/sw-test/app.js',
        '/sw-test/image-list.js',
        '/sw-test/star-wars-logo.jpg',
        '/sw-test/gallery/',
        '/sw-test/gallery/bountyHunters.jpg',
        '/sw-test/gallery/myLittleVader.jpg',
        '/sw-test/gallery/snowTroopers.jpg'
      ]);
    })
  );
});

3)installed(已安装)

在安装完成后,Service Worker就会进入installed状态。这时如果浏览器中还有其他页面运行着该Service Worker的旧版本,那么新的Service Worker就会一直处于等待的状态。

这里要注意,浏览器校验Service Worker是否发生更改是在页面完全加载以后,这时候如果Service Worker发生了更改,即使当前只打开了本页面,但由于旧的Service Worker已经在本页面上启动了,新的Service Worker还是需要等待下一次页面刷新的时候才会进入activating状态。

4) activating(激活中)

经过了installed状态,Service Worker就会进入activating状态,并且触发activate事件。这个时候,我们就可以为Web应用的完成一些清理过时资源的工作,例如删掉没用的资源文件,或者清空indexedDB中没用的数据。一旦完成清理的工作,我们就可以调用event.waitUntil方法告知浏览器Service Worker已经激活完成了。

self.addEventListener('activate', function (event) { // 监听worker的activate事件
    event.waitUntil( 
        //更新缓存 
      })
   )
});

5)fetch截取页面的资源请求

现在你已经将你的站点资源缓存了,你需要告诉 service worker 让它用这些缓存内容来做点什么。有了 fetch 事件,这是很容易做到的。



每次任何被 service worker 控制的资源被请求到时,都会触发 fetch 事件,这些资源包括了指定的 scope 内的文档,和这些文档内引用的其他任何资源(比如 index.html 发起了一个跨域的请求来嵌入一个图片,这个也会通过 service worker 。)

你可以给 service worker 添加一个 fetch 的事件监听器,接着调用 event 上的 respondWith() 方法来劫持我们的 HTTP 响应,然后你用可以用自己的魔法来更新他们。

this.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
  );
});

caches.match(event.request) 允许我们对网络请求的资源和 cache 里可获取的资源进行匹配,查看是否缓存中有相应的资源。这个匹配通过 url 和 vary header进行,就像正常的 http 请求一样。

上一篇 下一篇

猜你喜欢

热点阅读