workers标准让在Web App上拥有这些功能成为可能,

2019-09-18 17:53栏目:前端开发
TAG:

Service Worker初体验

2016/01/06 · JavaScript · Service Worker

原稿出处: AlloyTeam   

在2015年,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.  … …

正文以能源缓存为例,说美素佳儿(Friso)(Nutrilon)下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 在离线页面上有个暗藏的10日游(桌面版上按空格键,手提式有线电话机版上点击那只恐龙),这有一点能缓解一点你的苦闷。可是我们能够做得更加好。

Service workers 允许网址小编拦截自身站点的具有网络须要,那也就意味着大家得以提供周密的离线体验,就好像原生应用一样。在 Guardian 网址,大家前段时间上线了二个自定义的离线体验效果。当客商离线的时候,他们会看出五个包括Guardian 标记的页面,上边带有贰个简易的离线提醒,还会有一个填字游戏,他们能够在等待网络连接的时候玩玩这一个找点乐子。那篇博客解释了大家是什么样构建它的,可是在起来以前,你能够先自身尝试看。

Service Worker入门

2015/03/26 · JavaScript · Service Worker

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

  • 十年踪迹]()   

原生App具备Web应用普通所不有所的富离线体验,按时的默默无言更新,音信公告推送等职能。而新的Serviceworkers标准让在Web App上享有那一个效应成为大概。

生命周期

先来看一下四个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页面交互的作用在网页背后悄悄实践的力量。在将来,基于它能够完成新闻推送,静默更新以及地理围栏等劳务,但是当前它首先要具备的服从是阻挠和拍卖互联网必要,包涵可编制程序的响应缓存管理。

为何说这么些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。
  • Serviceworker大量使用promise,所以一旦你不通晓哪些是promise,那您须要先读书这篇文章。

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(UEvoqueL).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的文章。

打赏帮忙笔者翻译更加的多好文章,多谢!

打赏译者

瑟维斯 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

message事件

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

那是三个双向的经过,页面能够发消息给service worker,service worker也足以发送音信给页面,由于那一个特点,能够将service worker作为中间纽带,使得贰个域名仍然子域名下的三个页面能够随意通讯。

此间是三个小的页面之间通讯demo

打赏援救笔者翻译更多好作品,多谢!

图片 6

1 赞 收藏 评论

在我们开端写码在此之前

从这个系列地址拿到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掌握最好试行。

使用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的长河中,也境遇了部分标题,上面是里面四个

关于笔者:Erucy

图片 7

业已的SharePoint喵星程序员(临时还挂着微软MVP的名头),今后的Azure/.Net/MongoDB/Cordova/前端技术员,不经常写小说 个人主页 · 笔者的小说 · 46 ·   

图片 8

使用Service Worker

当今大家有了polyfill,况且解决了HTTPS,让大家看看到底怎么用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,你须求在您的页面上注册它。这一个手续告诉浏览器你的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,这样你可以关闭和再度张开它,而不会耳熟能详到您的新窗口。任何制造在模仿窗口中的注册服务和缓存在窗口被关门时都将未有。

难点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

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事件。

怎么缓存和重回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()方今仅帮助Service 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奥迪Q7的在同源下暗中认可发送凭据,但跨域时舍弃凭据的条条框框要来得好。fetch的展现更像其余的COLX570S央求,举个例子<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

Non-CO本田UR-VS默许不扶助

暗许意况下,从第三方U奇骏L跨域得到五个能源将会停业,除非对方援助了CO奔驰G级S。你能够增进叁个non-CO奥迪Q3S选项到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官网登录发布于前端开发,转载请注明出处:workers标准让在Web App上拥有这些功能成为可能,