service worker是一段脚本,workers标准让在Web App上有

2019-09-17 08:30栏目:前端开发
TAG:

Service Worker入门

2015/03/26 · JavaScript · Service Worker

初稿出处: Matt Gaunt   译文出处:[w3ctech

  • 十年踪迹]()   

原生App具有Web应用一般所不抱有的富离线体验,定期的沉默更新,新闻公告推送等作用。而新的Serviceworkers标准让在Web App上有着这么些功能成为恐怕。

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.  … …

本文以能源缓存为例,说圣元(Synutra)下service worker是怎么样专门的学问的。

连不上网?英帝国卫报的秉性离线页面是那般做的

2015/11/20 · HTML5 · Service Worker, 离线页面

本文由 伯乐在线 - Erucy 翻译,weavewillg 校稿。未经许可,禁止转发!
藏语出处:Oliver Ash。接待参加翻译组。

我们是怎么着运用 service worker 来为 theguardian.com 营造二个自定义的离线页面。

图片 1

theguardian.com 的离线页面。插图:奥利弗 Ash

您正在朝着公司途中的大巴里,在手提式有线电话机上展开了 Guardian 应用。大巴被隧道包围着,但是这一个应用能够符合规律运维,即使未有网络连接,你也能获得完全的效果,除了出示的内容大概有一些旧。假诺你品味在网址上也这么干,缺憾它完全无法加载:

图片 2

安卓版 Chrome 的离线页面

Chrome 中的那么些彩蛋,相当多个人都不亮堂》

Chrome 在离线页面上有个藏匿的十四日游(桌面版上按空格键,手机版上点击这只恐龙),那有些能缓慢化解一点您的烦恼。但是大家能够做得更加好。

Service workers 允许网址小编拦截本人站点的具备网络须求,那也就表示大家能够提供完善的离线体验,就如原生应用同样。在 Guardian 网址,我们如今上线了三个自定义的离线体验效果。当客商离线的时候,他们会看出二个分包 Guardian 标志的页面,上边带有八个归纳的离线提示,还恐怕有贰个填字游戏,他们得以在等候网络连接的时候玩玩这些找点乐子。那篇博客解释了我们是什么样营造它的,但是在始发此前,你能够先本身尝试看。

Service Worker 是什么?

一个 service worker 是一段运营在浏览器后台进度里的剧本,它独自于最近页面,提供了那二个不供给与web页面交互的功效在网页背后悄悄推行的技能。在今后,基于它可以兑现消息推送,静默更新以及地理围栏等劳动,可是近些日子它首先要具有的功能是阻挡和管理互联网诉求,包括可编制程序的响应缓存管理。

干什么说那几个API是一个格外棒的API呢?因为它使得开辟者能够帮忙相当好的离线体验,它赋予开垦者完全调控离线数据的才干。

在service worker建议在此之前,别的一个提供开荒者离线体验的API叫做App Cache。可是App Cache有些局限性,举例它能够很轻易地化解单页应用的主题材料,可是在多页应用上会很辛勤,而Serviceworkers的产出便是为了减轻App Cache的痛点。

下边详细说一下service worker有怎么着须要注意的地点:

  • 它是JavaScript Worker,所以它不能够平素操作DOM。可是service worker能够因此postMessage与页面之间通讯,把新闻文告给页面,若是供给的话,让页面自身去操作DOM。
  • Serviceworker是二个可编制程序的网络代理,允许开荒者调节页面上管理的互联网诉求。
  • 在不被选拔的时候,它会和谐终止,而当它再度被用到的时候,会被重复激活,所以您无法借助于service worker的onfecth和onmessage的管理函数中的全局状态。如若您想要保存一些长久化的音讯,你能够在service worker里使用IndexedDB API。
  • 瑟维斯worker大批量使用promise,所以只要你不打听怎么是promise,那你须求先读书这篇文章。

生命周期

先来看一下叁个service worker的运营周期

图片 3
上海体育场面是service worker生命周期,出处

图中得以看出,四个service worker要经历以下进度:

  1.  安装

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

图片 4

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

  2. 销毁,是还是不是销毁由浏览器决定,如果一个service worker长时间不行使可能机器内部存款和储蓄器有数,则恐怕会销毁这一个worker

试试看

你必要四个支持 Service Worker 和 fetch API 的浏览器。甘休到本文编写时只有Chrome(手提式无线电话机版和桌面版)相同的时候辅助这两种 API(译者注:Opera 近日也帮忙那多头),可是 Firefox 极快就要补助了(在每一日更新的版本中一度协理了),除去 Safari 之外的全体浏览器也都在研究。此外,service worker 只好登记在行使了 HTTPS 的网址上,theguardian.com 已经开头逐年搬迁到 HTTPS,所以大家只好在网址的 HTTPS 部分提供离线体验。就当下来讲,我们选择了 开拓者博客 作为我们用来测量试验的地点。所以只要您是在大家网址的 开拓者博客 部分阅读那篇文章的话,很幸运。

当你利用帮忙的浏览器访谈我们的 开荒者博客 中的页面的时候,一切就筹算伏贴了。断开你的互连网连接,然后刷新一下页面。假使您自身没条件尝试的话,能够看一下这段 演示录制(译者注:需梯子)。

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初次安装的生命周期:

图片 5

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的一处选择。

下边是在中,小编利用fetch api通过fliker的公然api获取图片的例子,注释中详细分解了每一步的机能:

JavaScript

/* 由于是get乞请,直接把参数作为query string传递了 */ var URL = ''; function fetch德姆o() { // fetch(url, option)协理五个参数,option中得以安装header、body、method消息fetch(UPAJEROL).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扶助。

办事规律

由此一段轻便的 JavaScript,大家得以提示浏览器在客户访谈页面包车型大巴时候登时登记我们分甘同苦的 service worker。如今支撑 service worker 的浏览器相当少,所以为了制止不当,大家要求采取个性检验。

JavaScript

if (navigator.serviceWorker) { navigator.serviceWorker.register('/service-worker.js'); }

1
2
3
if (navigator.serviceWorker) {
    navigator.serviceWorker.register('/service-worker.js');
}

Service worker 安装事件的一片段,大家得以接纳 新的缓存 API 来缓存大家网址中的种种内容,举个例子 HTML、CSS 和 JavaScript:

JavaScript

var staticCacheName = 'static'; var version = 1; function updateCache() { return caches.open(staticCacheName + version) .then(function (cache) { return cache.addAll([ '/offline-page.html', '/assets/css/main.css', '/assets/js/main.js' ]); }); }; self.addEventListener('install', function (event) { event.waitUntil(updateCache()); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var staticCacheName = 'static';
var version = 1;
 
function updateCache() {
    return caches.open(staticCacheName + version)
        .then(function (cache) {
            return cache.addAll([
                '/offline-page.html',
                '/assets/css/main.css',
                '/assets/js/main.js'
            ]);
        });
};
 
self.addEventListener('install', function (event) {
    event.waitUntil(updateCache());
});

当安装达成后,service worker 能够监听和垄断 fetch 事件,让咱们得以完全调控之后网址中发生的保有互连网央浼。

JavaScript

self.addEventListener('fetch', function (event) { event.respondWith(fetch(event.request)); });

1
2
3
self.addEventListener('fetch', function (event) {
    event.respondWith(fetch(event.request));
});

在此处大家有很灵活的半空中能够表明,比方上边那些关键,能够因此代码来生成我们和睦的央浼响应:

JavaScript

self.addEventListener('fetch', function (event) { var response = new Response('<h1>Hello, World!</h1>', { headers: { 'Content-Type': 'text/html' } }); event.respondWith(response); });

1
2
3
4
5
self.addEventListener('fetch', function (event) {
    var response = new Response('&lt;h1&gt;Hello, World!&lt;/h1&gt;',
        { headers: { 'Content-Type': 'text/html' } });
    event.respondWith(response);
});

再有那么些,倘若在缓存中找到了恳求相应的缓存,大家得以一直从缓存中回到它,假诺没找到的话,再通过网络获得响应内容:

JavaScript

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

1
2
3
4
5
6
7
8
self.addEventListener('fetch', function (event) {
    event.respondWith(
        caches.match(event.request)
            .then(function (response) {
                return response || fetch(event.request);
            })
    );
});

那正是说大家什么样利用这一个效率来提供离线体验呢?

率先,在 service worker 安装进程中,大家须要把离线页面要求的 HTML 和财富文件通过 service worker 缓存下来。在缓存中,大家加载了和煦支付的 填字游戏 的 React应用 页面。之后,我们会阻止全体访谈theguardian.com 互连网伏乞,满含网页、以及页面中的资源文件。管理那一个央求的逻辑大约如下:

  1. 当我们检查测试到传播央求是指向大家的 HTML 页面时,我们连年会想要提供最新的剧情,所以大家会尝试把那些须要通过互连网发送给服务器。
    1. 当大家从服务器获得了响应,就可以直接重临这几个响应。
    2. 假定网络乞求抛出了老大(比方因为客商掉线了),大家捕获那几个特别,然后采纳缓存的离线 HTML 页面作为响应内容。
  2. 要不然,当大家检查评定到央求的不是 HTML 的话,大家会从缓存中追寻响应的哀求内容。
    1. 要是找到了缓存内容,我们能够直接重临缓存的内容。
    2. 再不,大家会尝试把那么些乞求通过互连网发送给服务器。

在代码中,我们利用了 新的缓存 API(它是 Service Worker API 的一部分)以及 fetch 效能(用于转移网络须要),如下所示:

JavaScript

var doesRequestAcceptHtml = function (request) { return request.headers.get('Accept') .split(',') .some(function (type) { return type === 'text/html'; }); }; self.addEventListener('fetch', function (event) { var request = event.request; if (doesRequestAcceptHtml(request)) { // HTML pages fallback to offline page event.respondWith( fetch(request) .catch(function () { return caches.match('/offline-page.html'); }) ); } else { // Default fetch behaviour // Cache first for all other requests event.respondWith( caches.match(request) .then(function (response) { return response || fetch(request); }) ); } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var doesRequestAcceptHtml = function (request) {
    return request.headers.get('Accept')
        .split(',')
        .some(function (type) { return type === 'text/html'; });
};
 
self.addEventListener('fetch', function (event) {
    var request = event.request;
    if (doesRequestAcceptHtml(request)) {
        // HTML pages fallback to offline page
        event.respondWith(
            fetch(request)
                .catch(function () {
                    return caches.match('/offline-page.html');
                })
        );
    } else {
        // Default fetch behaviour
        // Cache first for all other requests
        event.respondWith(
            caches.match(request)
                .then(function (response) {
                    return response || fetch(request);
                })
        );
    }
});

就只需求如此多!theguardian.com 上的 持有代码都以在 GitHub 上开源 的,所以您能够去那儿查看大家的 service worker 的完好版本,可能直接从生产情形上访谈 。

作者们有丰富的说辞为那么些新的浏览器技术欢呼喝彩,因为它能够用来令你的网站像今日的原生应用一样,具备完善的离线体验。未来当 theguardian.com 完全迁移到 HTTPS 之后,离线页面包车型客车要害性会鲜明扩充,大家能够提供越发周到的离线体验。虚构一下您在上下班途中互连网比非常糟糕的时候访谈theguardian.com,你会看到特地为你订制的个性化内容,它们是在您前边访谈网址时由浏览器缓存下来的。它在装置进程中也不会发生任何不便,你所需求的只是访谈这些网址而已,不像原生应用,还索要客商有四个用到百货店的账号工夫安装。Serviceworker 一样能够扶持大家进步网址的加载速度,因为网址的框架能够被保证地缓存下来,仿佛原生应用一样。

假定你对 service worker 很感兴趣,想要明白越来越多内容的话,开辟者 马特Gaunt(Chrome的一寸丹心支持者)写了一篇越发详细地 介绍 Service Worker的文章。

打赏帮忙笔者翻译越来越多好文章,多谢!

打赏译者

在大家初始写码从前

从这个花色地址拿到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打探最棒实行。

message事件

页面和serviceWorker之间能够通过posetMessage()方法发送新闻,发送的音信能够透过message事件接收到。

那是二个双向的长河,页面能够发音讯给service worker,service worker也能够发送新闻给页面,由于那些特点,能够将service worker作为中间纽带,使得五个域名依旧子域名下的四个页面能够私下通讯。

这边是二个小的页面之间通讯demo

打赏支持作者翻译越多好小说,多谢!

图片 6

1 赞 收藏 评论

使用Service Worker

今天大家有了polyfill,并且解决了HTTPS,让我们看看毕竟怎么用service worker。

利用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对象,承袭自Extendable伊芙nt,在那之中的waitUntil()方法接收三个promise对象,直到那个promise对象成功resolve之后,才会一而再运营service-worker.js。
caches是多少个CacheStorage对象,使用open()方法张开多少个缓存,缓存通过名称实行区分。
获得cache实例之后,调用addAll()方法缓存文件。

与上述同类就将文件增加到caches缓存中了,想让浏览器采取缓存,还需求拦截fetch事件

JavaScript

// 缓存图片 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; }); }) ) });

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的进度中,也遇到了有个别主题素材,上面是中间三个

至于作者:Erucy

图片 7

曾经的SharePoint喵星技术员(暂且还挂着微软MVP的名头),以后的Azure/.Net/MongoDB/Cordova/前端程序员,不常写小说 个人主页 · 小编的稿子 · 46 ·   

图片 8

何以注册和装置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是否对你的网站启用了。

图片 9

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

您会意识那几个效应能够很有益于地在三个模拟窗口中测量试验你的service worker,那样您可以关闭和另行伸开它,而不会影响到你的新窗口。任何创造在模拟窗口中的注册服务和缓存在窗口被关闭时都将一无往返。

标题1. 运转时刻

service worker并非一贯在后台运营的。在页面关闭后,浏览器能够承接维持service worker运维,也得以关闭service worker,那有赖于与浏览器自个儿的行事。所以不要定义一些全局变量,举例上面包车型地铁代码(来自):

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的剧本里来,在这里面,大家要到位它的装置步骤。

在最大旨的例子中,你要求为install事件定义二个callback,并垄断如何文件你想要缓存。

JavaScript

// The files we want to cache var urlsToCache = [ '/', '/styles/main.css', '/script/main.js' ]; // Set the callback for the install step self.addEventListener('install', function(event) { // Perform install steps });

1
2
3
4
5
6
7
8
9
10
11
// The files we want to cache
var urlsToCache = [
  '/',
  '/styles/main.css',
  '/script/main.js'
];
 
// Set the callback for the install step
self.addEventListener('install', function(event) {
    // Perform install steps
});

在我们的install callback中,大家须求试行以下步骤:

  1. 敞开一个缓存
  2. 缓存大家的文本
  3. 支配是或不是具有的能源是或不是要被缓存

JavaScript

var CACHE_NAME = 'my-site-cache-v1'; var urlsToCache = [ '/', '/styles/main.css', '/script/main.js' ]; self.addEventListener('install', function(event) { // Perform install steps event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) { console.log('Opened cache'); return cache.addAll(urlsToCache); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
  '/',
  '/styles/main.css',
  '/script/main.js'
];
 
self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

地方的代码中,大家经过caches.open展开大家钦定的cache文件名,然后大家调用cache.addAll并传播我们的公文数组。这是由此多元promise(caches.open 和 cache.addAll)完结的。event.waitUntil得到八个promise并行使它来收获安装开销的时日以及是还是不是安装成功。

如若具有的文件都被缓存成功了,那么service worker就设置成功了。倘若别的三个文件下载退步,那么安装步骤就能够停业。那一个情势允许你依赖于你和煦内定的有所财富,可是那表示你供给特别小心地调控如何文件须要在设置步骤中被缓存。钦赐了太多的公文的话,就能增多设置失败率。

上边只是三个轻松易行的例证,你能够在install事件中实施其他操作依旧以致忽视install事件。

主题材料2. 权力太大

当service worker监听fetch事件随后,对应的呼吁都会透过service worker。通过chrome的network工具,可以见到此类央求会标明:from service worker。如若service worker中出现了难题,会招致全数央浼退步,包罗常见的html文件。所以service worker的代码品质、容错性必定要很好本事确定保障web app正常运营。

 

参照小说:

1. 

2. 

3. 

4. 

5. 

1 赞 3 收藏 评论

图片 10

怎么样缓存和重返Request

你早已设置了service worker,你未来得以重回您缓存的央浼了。

当service worker棉被服装置成功还要客户浏览了另八个页面恐怕刷新了当下的页面,service worker将初始收受到fetch事件。上边是三个例子:

JavaScript

self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return response if (response) { return response; } return fetch(event.request); } ) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
 
        return fetch(event.request);
      }
    )
  );
});

地方的代码里大家定义了fetch事件,在event.respondWith里,大家传入了几个由caches.match产生的promise.caches.match 查找request中被service worker缓存命中的response。

假诺大家有叁个命中的response,我们回来被缓存的值,不然大家回来贰个实时从网络乞求fetch的结果。那是二个非常轻巧的例证,使用具备在install步骤下被缓存的财富。

假诺大家想要增量地缓存新的乞请,大家能够经过管理fetch央求的response并且增加它们到缓存中来落到实处,例如:

JavaScript

self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return response if (response) { return response; } // IMPORTANT: Clone the request. A request is a stream and // can only be consumed once. Since we are consuming this // once by cache and once by the browser for fetch, we need // to clone the response var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { // Check if we received a valid response if(!response || response.status !== 200 || response.type !== 'basic') { return response; } // IMPORTANT: Clone the response. A response is a stream // and because we want the browser to consume the response // as well as the cache consuming the response, we need // to clone it so we have 2 stream. var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
 
        // IMPORTANT: Clone the request. A request is a stream and
        // can only be consumed once. Since we are consuming this
        // once by cache and once by the browser for fetch, we need
        // to clone the response
        var fetchRequest = event.request.clone();
 
        return fetch(fetchRequest).then(
          function(response) {
            // Check if we received a valid response
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }
 
            // IMPORTANT: Clone the response. A response is a stream
            // and because we want the browser to consume the response
            // as well as the cache consuming the response, we need
            // to clone it so we have 2 stream.
            var responseToCache = response.clone();
 
            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });
 
            return response;
          }
        );
      })
    );
});

代码里大家所做作业包涵:

  1. 累加一个callback到fetch伏乞的 .then 方法中
  2. 假诺大家获得了贰个response,大家举行如下的自己商讨:
    1. 担保response是可行的
    2. 反省response的气象是不是是200
    3. 担保response的花色是basic,那意味着央浼小编是同源的,非同源(即跨域)的伏乞也不能够被缓存。
  3. 一经我们透过了反省,clone那些诉求。这么做的因由是假诺response是贰个Stream,那么它的body只可以被读取三遍,所以大家得将它克隆出来,一份发给浏览器,一份发给缓存。

如何立异三个Service Worker

您的service worker总有须要更新的那一天。当那一天来临的时候,你须要遵守如下步骤来更新:

  1. 履新您的service worker的JavaScript文件
    1. 当客商浏览你的网址,浏览器尝试在后台下载service worker的台本文件。只要服务器上的文本和当麻芋果件有叁个字节差异,它们就被推断为须要创新。
  2. 更新后的service worker将起来运维,install event被重新触发。
  3. 在这几个日子节点上,当前页不熟悉效的照样是老版本的service worker,新的servicer worker将步入”waiting”状态。
  4. 目前页面被关门之后,老的service worker进程被杀死,新的servicer worker正式生效。
  5. 设若新的service worker生效,它的activate事件被触发。

代码更新后,通常供给在activate的callback中实践三个管制cache的操作。因为您会必要排除掉在此之前旧的数额。我们在activate实际不是install的时候实践这么些操作是因为假若大家在install的时候即刻实施它,那么照旧在运作的旧版本的数据就坏了。

事先大家只使用了二个缓存,叫做my-site-cache-v1,其实我们也可以使用多个缓存的,例如一个给页面使用,一个给blog的内容提交使用。这意味着,在install步骤里,我们可以创建两个缓存,pages-cache-v1和blog-posts-cache-v1,在activite步骤里,我们可以删除旧的my-site-cache-v1。

下边包车型的士代码能够循环全部的缓存,删除掉全部不在白名单中的缓存。

JavaScript

self.addEventListener('activate', function(event) { var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1']; event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (cacheWhitelist.indexOf(cacheName) === -1) { return caches.delete(cacheName); } }) ); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
self.addEventListener('activate', function(event) {
 
  var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
 
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

管理边界和填坑

这一节内容相比新,有成都百货上千待定细节。希望这一节十分的快就无需讲了(因为标准会管理这么些主题素材——译者注),可是今后,这几个剧情照旧应该被提一下。

借使设置失败了,未有很优雅的不二秘诀取得通报

设若两个worker被注册了,不过从未出现在chrome://inspect/#service-workers或chrome://serviceworker-internals,那么很可能因为异常而安装失败了,或者是产生了一个被拒绝的的promise给event.waitUtil。

要消除那类难题,首先到 chrome://serviceworker-internals检查。打开开发者工具窗口准备调试,然后在你的install event代码中添加debugger;语句。这样,通过断点调试你更容易找到问题。

fetch()方今仅扶助瑟维斯 Workers

fetch立即补助在页面上选取了,然而前段时间的Chrome完结,它还只帮忙service worker。cache API也将在在页面上被辅助,可是近期截至,cache也还只好在service worker中用。

fetch()的私下认可参数

当您使用fetch,缺省级地区级,央求不会带上cookies等证据,要想带上的话,需求:

JavaScript

fetch(url, { credentials: 'include' })

1
2
3
fetch(url, {
  credentials: 'include'
})

如此设计是有理由的,它比XH中华V的在同源下默许发送凭据,但跨域时吐弃凭据的平整要来得好。fetch的一坐一起更像任何的CO大切诺基S央浼,比如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

Non-CO传祺S暗许不支持

暗许意况下,从第三方U卡宴L跨域得到一个能源将会倒闭,除非对方帮助了CORAV4S。你能够加多二个non-COEnclaveS选项到Request去幸免退步。代价是那般做会回到二个“不透明”的response,意味着你不可能查出那么些央浼毕竟是打响了照旧败诉了。

JavaScript

cache.addAll(urlsToPrefetch.map(function(urlToPrefetch) { return new Request(urlToPrefetch, { mode: 'no-cors' }); })).then(function() { console.log('All resources have been fetched and cached.'); });

1
2
3
4
5
cache.addAll(urlsToPrefetch.map(function(urlToPrefetch) {
  return new Request(urlToPrefetch, { mode: 'no-cors' });
})).then(function() {
  console.log('All resources have been fetched and cached.');
});

fetch()不根据30x重定向标准

噩运,重定向在fetch()中不会被触发,这是眼前版本的bug;

拍卖响应式图片

img的srcset属性可能<picture>标签会根据情况从浏览器或者网络上选择最合适尺寸的图片。

在service worker中,你想要在install步骤缓存三个图片,你有以下两种选拔:

  1. 安装具有的<picture>元素或者将被请求的srcset属性。
  2. 设置单一的low-res版本图片
  3. 设置单一的high-res版本图片

比较好的方案是2或3,因为假如把装有的图样都给下载下来存着有一点浪费内部存款和储蓄器。

假设你将low-res版本在install的时候缓存了,然后在页面加载的时候你想要尝试从网络上下载high-res的版本,可是要是high-res版本下载战败以来,就依旧用low-res版本。这一个主见很好也值得去做,然而有八个主题素材:

假诺大家有下边二种图片:

Screen Density Width Height
1x 400 400
2x 800 800

HTML代码如下:

JavaScript

<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x" />

1
<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x" />

若果大家在八个2x的显得情势下,浏览器会下载image-2x.png,假如大家离线,你可以读取从前缓存并重临image-src.png替代,假使在此之前它曾经被缓存过。固然如此,由于明日的格局是2x,浏览器会把400X400的图样呈现有200X200,要制止那一个主题材料即就要图纸的样式上设置宽高。

JavaScript

<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x" style="width:400px; height: 400px;" />

1
2
<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x"
style="width:400px; height: 400px;" />

图片 11

<picture>标签情况更复杂一些,难度取决于你是如何创建和使用的,但是可以通过与srcset类似的思路去解决。

改变URL Hash的Bug

在M40版本中设有贰个bug,它会让页面在更换hash的时候形成service worker结束职业。

您能够在此地找到越来越多相关的新闻: 

更加多内容

这边有局地相关的文档能够参照他事他说加以考察:

获取救助

假如你相逢麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于大家当下跟进和不择花招扶助你消除难点。

赞 2 收藏 评论

图片 12

版权声明:本文由大奖888-www.88pt88.com-大奖888官网登录发布于前端开发,转载请注明出处:service worker是一段脚本,workers标准让在Web App上有