菜单

Service Worker初体验

2019年10月5日 - XML

主题材料1. 运维时刻

service
worker并不是直接在后台运营的。在页面关闭后,浏览器能够延续保持service
worker运转,也能够关闭service
worker,那有赖于与浏览器自个儿的作为。所以实际不是定义一些全局变量,举例下边的代码(来自https://jakearchibald.com/2014/service-worker-first-draft/):

JavaScript

var hitCounter = 0; this.addEventListener(‘fetch’, function(event) {
hitCounter++; event.respondWith( new Response(‘Hit number ‘ +
hitCounter) ); });

1
2
3
4
5
6
7
8
var hitCounter = 0;
 
this.addEventListener(‘fetch’, function(event) {
  hitCounter++;
  event.respondWith(
    new Response(‘Hit number ‘ + hitCounter)
  );
});

回去的结果可能是未曾规律的:1,2,1,2,1,1,2….,原因是hitCounter并未向来留存,若是浏览器关闭了它,下一次起动的时候hitCounter就赋值为0了
如此的专业导致调节和测量检验代码困难,当您更新三个service
worker将来,唯有在开采新页面以往才恐怕选用新的service
worker,在调节和测验进度中常常等上一两分钟才会使用新的,比较抓狂。

Service Worker生命周期

service worker具备八个完全部独用立于Web页面包车型大巴生命周期

图片 1

sw-lifecycle.png

  1. 挂号service worker,在网页上生效
  2. 设置成功,激活 可能 安装战败(下一次加载会尝试重新安装)
  3. 激活后,在sw的效应域下作用有所的页面,第一遍决定sw不会生效,下一次加载页面才会收效。
  4. sw成效页面后,管理fetch(网络哀告)和message(页面音信)事件 也许被终止(节省里部存款和储蓄器)。

选取service workder缓存文件

上面介绍一个运用service worker缓存离线文件的例证
预备index.js,用于注册service-worker

JavaScript

if (navigator.serviceWorker) {
navigator.serviceWorker.register(‘service-worker.js’).then(function(registration)
{ console.log(‘service worker 注册成功’); }).catch(function (err) {
console.log(‘servcie worker 注册战败’) }); }

1
2
3
4
5
6
7
if (navigator.serviceWorker) {
    navigator.serviceWorker.register(‘service-worker.js’).then(function(registration) {
        console.log(‘service worker 注册成功’);
    }).catch(function (err) {
        console.log(‘servcie worker 注册失败’)
    });
}

在上述代码中,注册了service-worker.js作为当前路径下的service
worker。由于service
worker的权杖非常高,全部的代码都急需是安全可信的,所以独有https站点能力够使用service
worker,当然localhost是三个特例。
登记结束,今后开班写service-worker.js代码。
依据前边的生命周期图,在三个新的service
worker被注册之后,首先会触发install事件,在service-workder.js中,能够透过监听install事件张开局地最初化工作,或许哪些也不做。
因为我们是要缓存离线文件,所以能够在install事件中初阶缓存,可是只是将文件加到caches缓存中,真正想让浏览器选择缓存文件须求在fetch事件中阻止

JavaScript

var cacheFiles = [ ‘about.js’, ‘blog.js’ ];
self.addEventListener(‘install’, function (evt) { evt.waitUntil(
caches.open(‘my-test-cahce-v1’).then(function (cache) { return
cache.addAll(cacheFiles); }) ); });

1
2
3
4
5
6
7
8
9
10
11
var cacheFiles = [
    ‘about.js’,
    ‘blog.js’
];
self.addEventListener(‘install’, function (evt) {
    evt.waitUntil(
        caches.open(‘my-test-cahce-v1’).then(function (cache) {
            return cache.addAll(cacheFiles);
        })
    );
});

第一定义了须要缓存的公文数组cacheFile,然后在install事件中,缓存这个文件。
evt是一个InstallEvent对象,承继自ExtendableEvent,个中的waitUntil()方法接收三个promise对象,直到这几个promise对象成功resolve之后,才会一连运转service-worker.js。
caches是叁个CacheStorage对象,使用open()方法打开三个缓存,缓存通过名称进行区分。
获取cache实例之后,调用addAll()方法缓存文件。

如此就将文件加多到caches缓存中了,想让浏览器采取缓存,还须求拦截fetch事件

JavaScript

// 缓存图片 self.add伊夫ntListener(‘fetch’, function (evt) {
evt.respondWith( caches.match(evt.request).then(function(response) { if
(response) { return response; } var request = evt.request.clone();
return fetch(request).then(function (response) { if (!response &&
response.status !== 200 &&
!response.headers.get(‘Content-type’).match(/image/)) { return response;
} var responseClone = response.clone();
caches.open(‘my-test-cache-v1’).then(function (cache) {
cache.put(evt.request, responseClone); }); return response; }); }) ) });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 缓存图片
self.addEventListener(‘fetch’, function (evt) {
    evt.respondWith(
        caches.match(evt.request).then(function(response) {
            if (response) {
                return response;
            }
            var request = evt.request.clone();
            return fetch(request).then(function (response) {
                if (!response && response.status !== 200 && !response.headers.get(‘Content-type’).match(/image/)) {
                    return response;
                }
                var responseClone = response.clone();
                caches.open(‘my-test-cache-v1’).then(function (cache) {
                    cache.put(evt.request, responseClone);
                });
                return response;
            });
        })
    )
});

透过监听fetch事件,service worker能够回去本人的响应。

第一检缓存中是还是不是早就缓存了这么些诉求,假若有,就平昔重返响应,就减弱了二遍网络诉求。不然由service
workder发起央求,那时的service workder起到了壹在那之中间代理的功力。

service worker央浼的进度通过fetch
api完毕,获得response对象现在实行过滤,查看是不是是图片文件,若是或不是,就平昔回到乞请,不会缓存。

如借使图形,要先复制一份response,原因是request大概response对象属于stream,只可以动用二次,之后一份存入缓存,另一份发送给页面。
那就是service worker的精锐之处:拦截供给,伪造响应。fetch
api在此处也起到了极大的效果。

 

service
worker的翻新很简短,只要service-worker.js的文本内容有更新,就能够利用新的本子。可是有一点要小心:旧缓存文件的解决、新文件的缓存要在activate事件中开展,因为大概旧的页面还在利用以前的缓存文件,清除之后会失去功效。

 

在首先使用service worker的进程中,也碰到了部分难点,上面是中间八个

调度工具

在调试的时候能够用来unregister、stop、start等操作

chrome访问chrome://inspect/#service-workerschrome://serviceworker-internals查看service-workers

图片 2

chrome-tool-1.png

图片 3

chrome-tool-2.png

firefox通过about:debugging#workers查看

图片 4

firefox-tool.png

越来越多请参见debugging-service-workers

难题2. 权力太大

当service worker监听fetch事件随后,对应的需要都会因此service
worker。通过chrome的network工具,能够看看此类央浼会标注:from service
worker。倘使service
worker中冒出了难点,会促成全数央求退步,满含常见的html文件。所以service
worker的代码品质、容错性应当要很好技巧确认保障web app符合规律运转。

 

参照他事他说加以考察小说:

1. http://www.html5rocks.com/en/tutorials/service-worker/introduction/

2. http://www.sitepoint.com/introduction-to-the-fetch-api/

3. https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent

4. https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent

5. https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage

1 赞 3 收藏
评论

图片 5

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。

fetch事件

在页面发起http诉求时,service
worker能够透过fetch事件拦截央求,何况付诸自个儿的响应。
w3c提供了贰个新的fetch
api,用于代替XMLHttpRequest,与XMLHttpRequest最大分裂有两点:

1.
fetch()方法重临的是Promise对象,通过then方法实行连接调用,减少嵌套。ES6的Promise在改为正式之后,会更为便利开荒职员。

2. 提供了Request、Response对象,要是做过后端开采,对Request、Response应该相比纯熟。前端要提倡呼吁可以透过url发起,也得以选择Request对象发起,况且Request能够复用。可是Response用在哪个地方吗?在service
worker现身此前,前端确实不会融洽给和煦发新闻,不过有了service
worker,就能够在阻碍央求之后据书上说供给发回本身的响应,对页面来说,这么些普通的诉求结果并不曾差距,那是Response的一处采纳。

上面是在http://www.sitepoint.com/introduction-to-the-fetch-api/中,小编辑访谈取fetch
api通过fliker的公开api获取图片的事例,注释中详尽解释了每一步的作用:

JavaScript

/* 由于是get央求,直接把参数作为query string传递了 */ var URL =
https://api.flickr.com/services/rest/?method=flickr.photos.search&api\_key=your\_api\_key&format=json&nojsoncallback=1&tags=penguins‘;
function fetch德姆o() { // fetch(url,
option)帮忙多个参数,option中得以设置header、body、method消息fetch(U奥迪Q3L).then(function(response) { // 通过promise
对象获得对应内容,并且将响应内容依照json格式转成对象,json()方法调用之后回到的照旧是promise对象
// 也能够把内容转化成arraybuffer、blob对象 return response.json();
}).then(function(json) { // 渲染页面 insertPhotos(json); }); }
fetch德姆o();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 由于是get请求,直接把参数作为query string传递了 */
var URL = ‘https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=your_api_key&format=json&nojsoncallback=1&tags=penguins’;
 
function fetchDemo() {
  // fetch(url, option)支持两个参数,option中可以设置header、body、method信息
  fetch(URL).then(function(response) {
    // 通过promise 对象获得相应内容,并且将响应内容按照json格式转成对象,json()方法调用之后返回的依然是promise对象
    // 也可以把内容转化成arraybuffer、blob对象
    return response.json();
  }).then(function(json) {
    // 渲染页面
    insertPhotos(json);
  });
}
 
fetchDemo();

fetch
api与XMLHttpRequest相比,特别从简,并且提供的功效更宏观,财富拿到方式比ajax更加高雅。包容性方面:chrome
42伊始辅助,对于旧浏览器,能够透过合法维护的polyfill帮忙。

离线阅读

message事件

页面和serviceWorker之间能够通过posetMessage()方法发送消息,发送的音信可以经过message事件接收到。

那是一个双向的进度,页面能够发新闻给service worker,service
worker也足以发送信息给页面,由于那几个性情,能够将service
worker作为中间纽带,使得二个域名照旧子域名下的多个页面能够随便通信。

那边是三个小的页面之间通讯demohttps://nzv3tos3n.qnssl.com/message/msg-demo.html

缓存版本管理

本子修改的时候会触发activate,将旧版本的缓存清理掉。

var OFFLINE_PREFIX = 'offline-';
var CACHE_NAME = 'main_v1.0.0';
self.addEventListener('activate', function(event) {
  var mainCache = [CACHE_NAME];
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if ( mainCache.indexOf(cacheName) === -1 && cacheName.indexOf(OFFLINE_PREFIX) === -1 ) {
            // When it doesn't match any condition, delete it.
            console.info('SW: deleting ' + cacheName);
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
  return self.clients.claim();
});

Service Worker初体验

2016/01/06 · JavaScript
· Service Worker

原稿出处: AlloyTeam   

在二零一五年,W3C公布了service worker的草案,service
worker提供了不胜枚举新的工夫,使得web app具有与native
app一样的离线体验、消息推送体验。
service worker是一段脚本,与web
worker同样,也是在后台运维。作为三个单独的线程,运营条件与日常脚本不一致,所以无法直接参预web交互行为。native
app能够产生离线使用、新闻推送、后台自动更新,service
worker的产出是幸而为了使得web app也足以具有类似的力量。

 

service worker可以:

  1. 后台音讯传递
  2. 网络代理,转载呼吁,伪造响应
  3. 离线缓存
  4. 音讯推送
  5.  … …

正文以财富缓存为例,说美赞臣(Meadjohnson)下service worker是什么行事的。

离线存款和储蓄数据

对U牧马人L寻址能源,使用Cache
API
。对任何数据,使用IndexedDB。

生命周期

先来看一下多个service worker的周转周期

图片 6
上海体育地方是service
worker生命周期,出处http://www.html5rocks.com/en/tutorials/service-worker/introduction/

图中能够看见,三个service worker要经历以下进程:

  1.  安装

2.
 激活,激活成功以后,展开chrome://inspect/#service-workers能够查阅到当下运作的service
worker

图片 7

  1. 监听fetch和message事件,上边二种事件会开展简易描述

  2. 销毁,是否销毁由浏览器决定,假若三个service
    worker短期不利用可能机器内部存款和储蓄器有数,则恐怕会销毁那几个worker

从缓存中加载

service
worker成功注册,並且顾客浏览了另一个页面恐怕刷新了脚下的页面,service
worker将起来接到到fetch事件。

截留互联网乞求并选用缓存,缓存命中,重临缓存财富,不然再次来到二个实时从网络央求fetch的结果。

self.addEventListener('fetch', function(event) {
  var requestUrl = new URL(event.request.url);
  if (requestUrl.origin === location.origin) {
      if (requestUrl.pathname === '/') {
      event.respondWith(
        caches.open(cacheName).then(function(cache) {
          return fetch(event.request).then(function(networkResponse) {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          }).catch(function() {
            return cache.match(event.request);
          });
        })
      );
    }
  }

  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

https

Server要求协助https

透过service
worker能够勒迫连接,伪造和过滤响应,为了防止那一个难题,只好在HTTPS的网页上登记service
workers,幸免加载service worker的时候不被歹徒篡改。

Github Pages是HTTPS的,能够通过Github做一些品尝

参考

原理

简书放不了demo,demo能够看原文

缓存站点的财富

概念须求缓存的公文,然后在sw注册安装后赶回cache
Api将财富文件写入缓存。假诺全数的文书都被缓存成功了,那么service
worker就安装成功了。即使别的贰个文书下载战败,那么安装步骤就能失败。

var cacheName = 'v1';
var assetsToCache = [
  '/styles/main.css',
  '/script/main.js'
];

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(cacheName).then(function(cache) {
      return cache.addAll(assetsToCache);
    }).then(function() {
      return self.skipWaiting();
    })
  );
});

注册 service worker

创立贰个 JavaScript 文件(举个例子:sw.js)作为 service worker

报告浏览器注册这一个JavaScript文件为service worker,检查service worker
API是还是不是可用,假如可用就注册service worker

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);
  });
}

sw.js文件被放在那几个域的根目录下,和网址同源。那一个service
work将会吸取这一个域下的有着fetch事件。

若果将service worker文件注册为/example/sw.js,那么,service
worker只好抽出/example/路线下的fetch事件(举个例子: /example/page1/,
/example/page2/)。

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

  var currentPath = window.location.pathname;
  var cacheButton = document.querySelector('.offline-btn');

  var imageArray = document.querySelectorAll('img');
  if(cacheButton) {
    cacheButton.addEventListener('click', function(event) {
      event.preventDefault();
      // 缓存当前链接和使用的图片
      var pageResources = [currentPath];
      for (i = 0; i < imageArray.length; i++) {
        pageResources.push(imageArray[i].src);
      }
      caches.open('offline-' + currentPath).then(function(cache) {
        var updateCache = cache.addAll(pageResources);

        updateCache.then(function() {
          console.log('Article is now available offline.');
          cacheButton.innerHTML = "☺";
        });

        updateCache.catch(function (error) {
          console.log('Article could not be saved offline.');
          cacheButton.innerHTML = "☹";
        });
      });
    });
  }
}

Service Worker 库

Service Worker补助使用

浏览器帮助

service worker
support

图片 8

navigator-serviceworker.png

polyfill

使用ServiceWorker cache
polyfill
让旧版本浏览器援助ServiceWorker cache API,

demo

使用https访问本文,展开ChromeDevTools,选取Application选项卡->ServiceWorkers

图片 9

sw-devtools.png

能够看来Service Workers注册

点击下边离线保存开关

<button class=”btn btn-sm btn-primary
offline-btn”>离线保存</button>

接下来选拔Cache Storage,可以看来文字内容早就缓存到Cache Storage

图片 10

sw-cache.png

然后采纳Service Workers 勾选
Offline,NetWork出现了⚠️️,然后试试离线访谈本文

图片 11

sw-offline.png

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图