连不上网

作者: 前端应用  发布:2019-11-04

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卡塔 尔(英语:State of Qatar)下service worker是什么样专门的职业的。

连不上网?United Kingdom卫报的秉性离线页面是如此做的

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的运转周期

图片 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(手提式有线电话机版和桌面版卡塔 尔(英语:State of Qatar)同一时间援救这三种 API(译者注:Opera 目前也扶助那二者卡塔尔,但是 Firefox 非常的慢将要援助了(在每一天更新的版本中早已扶持了卡塔尔国,除却 Safari 之外的有所浏览器也都在搜求。其余,service worker 只可以登记在接纳了 HTTPS 的网址上,theguardian.com 已经上马逐年搬迁到 HTTPS,所以我们只可以在网址的 HTTPS 部分提供离线体验。就当前以来,我们选取了 开垦者博客 作为大家用来测量试验的地点。所以只要您是在大家网址的 开采者博客 部分阅读这篇作品的话,很幸运。

当您利用扶持的浏览器访谈我们的 开辟者博客 中的页面包车型地铁时候,一切就酌量稳当了。断开你的网络连接,然后刷新一下页面。要是你谐和没标准尝试的话,能够看一下这段 示范录像(译者注:需梯子)。

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(U讴歌ZDXL).then(function(response) { // 通过promise 对象获得相应内容,并且将响应内容遵照json格式转成对象,json()方法调用之后重返的仍是promise对象 // 也得以把内容转产生arraybuffer、blob对象 return response.json(); }).then(function(json) { // 渲染页面 insertPhotos(json); }); } fetchDemo();

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. 尽管网络央求抛出了那多少个(比方因为客户掉线了卡塔 尔(英语:State of Qatar),大家捕获这一个丰盛,然后利用缓存的离线 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 很感兴趣,想要驾驭越来越多内容的话,开拓者 MattGaunt(Chrome的忠诚扶植者卡塔 尔(阿拉伯语:قطر‎写了意气风发篇特别详实地 介绍 Service Worker的文章。

打赏帮助作者翻译更加多好文章,多谢!

打赏译者

message事件

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

那是叁个双向的进度,页面能够发新闻给service worker,service worker也能够发送音讯给页面,由于那些特点,能够将service worker作为中间纽带,使得二个域名照旧子域名下的四个页面能够任性通信。

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

打赏援救本身翻译更加多好小说,多谢!

图片 5

1 赞 收藏 评论

行使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

图片 6

早已的SharePoint喵星程序员(暂且还挂着微软MVP的名头卡塔尔国,将来的Azure/.Net/MongoDB/Cordova/前端技术员,不时写小说 个人主页 · 作者的稿子 · 46 ·   

图片 7

标题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,在调解进度中时时等上风度翩翩两秒钟才会动用新的,相比较抓狂。

难题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 收藏 评论

图片 8

本文由贝博体育app发布于前端应用,转载请注明出处:连不上网

关键词:

上一篇:CSS布局华而不实,CSS常用网页布局工夫
下一篇:没有了