workers规范让在Web App上具备这么些效应成为大概

2019-09-22 02:27栏目:前端开发
TAG:

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

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

本文由 伯乐在线 - Erucy 翻译,weavewillg 校稿。未经许可,禁止转发!
立陶宛(Lithuania)语出处:Oliver Ash。款待加入翻译组。

咱俩是哪些使用 service worker 来为 theguardian.com 营造三个自定义的离线页面。

图片 1

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

您正在朝着集团途中的大巴里,在手提式有线电电话机上展开了 Guardian 应用。大巴被隧道包围着,不过那几个应用能够平常运营,尽管未有互连网连接,你也能博得完全的效果与利益,除了展现的源委大概有一些旧。假若您品尝在网址上也这么干,缺憾它完全无法加载:

图片 2

安卓版 Chrome 的离线页面

Chrome 中的那些彩蛋,很五人都不掌握》

Chrome 在离线页面上有个暗藏的玩耍(桌面版上按空格键,手提式有线电电话机版上点击那只恐龙),那有个别能缓和一点你的郁闷。不过大家得以做得更好。

Service workers 允许网址笔者拦截自身站点的持有互连网央浼,那也就表示大家能够提供完善的离线体验,就疑似原生应用同样。在 Guardian 网址,大家近来上线了贰个自定义的离线体验效果。当客户离线的时候,他们会看到三个满含Guardian 标记的页面,上边带有多少个差不离的离线提醒,还应该有八个填字游戏,他们能够在伺机网络连接的时候玩玩那个找点乐子。那篇博客解释了大家是怎样营造它的,可是在上马从前,你能够先本身试试看。

利用 Service worker 创造三个非常轻巧的离线页面

2016/06/07 · JavaScript · 1 评论 · Service Worker

本文由 伯乐在线 - 刘健超-J.c 翻译,艾凌风 校稿。未经许可,禁止转载!
朝鲜语出处:Dean Hume。款待参加翻译组。

让大家想像以下场景:大家那儿在一辆通往农村的火车上,用移动设备望着一篇很棒的小说。与此同期,当您点击“查看越来越多”的链接时,火车猛然步向了隧道,导致运动器材失去了互联网,而 web 页面会呈现出类似以下的内容:

图片 3

那是非常令人颓败的体会!幸运的是,web 开垦者们能经过一些新特点来创新这类的客商体验。笔者多年来直接在折腾 ServiceWorkers,它给 web 带来的数不胜数恐怕性总能给本身欣喜。Service Workers 的好好特质之一是允许你检查实验互联网央浼的场景,并使你作出相应的响应。

在那篇文章里,我企图用此特性检查顾客的眼下互联网连接境况,要是没连接则赶回一个超级级容易的离线页面。就算那是贰个要命基础的案例,但它能给你带来启发,让你理解运行并运转该天性是何其的轻巧!如若你没理解过 Service Worker,笔者建议您看看此 Github repo,掌握越来越多相关的信息。

在该案例先河前,让我们先简单地看看它的办事流程:

  1. 在客商第三回访谈大家的页面时,大家会安装 ServiceWorker,并向浏览器的缓存增多我们的离线 HTML 页面
  2. 然后,如若客户图谋导航到另贰个 web 页面(同三个网址下),但此时已断网,那么大家将赶回已被缓存的离线 HTML 页面
  3. 唯独,纵然客户筹划导航到别的一个 web 页面,而此刻互连网已接二连三,则能照常浏览页面

Service Worker入门

2015/03/26 · JavaScript · Service Worker

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

  • 十年踪迹]()   

原生App拥有Web应用一般所不具备的富离线体验,定期的沉默更新,音讯文告推送等功用。而新的Serviceworkers标准让在Web App上独具这几个职能成为大概。

试试看

您要求一个协助 Service Worker 和 fetch API 的浏览器。结束到本文编写时只有Chrome(手提式有线电话机版和桌面版)同期协助这两种 API(译者注:Opera 这段日子也援救这两个),但是 Firefox 十分的快将在帮忙了(在每一天更新的版本中已经支撑了),除去 Safari 之外的具备浏览器也都在实行。另外,service worker 只可以登记在选取了 HTTPS 的网址上,theguardian.com 已经上马稳步搬迁到 HTTPS,所以大家不得不在网址的 HTTPS 部分提供离线体验。就当前的话,我们挑选了 开采者博客 作为大家用来测量检验的地点。所以一旦您是在我们网址的 开荒者博客 部分阅读这篇作品的话,很幸运。

当您使用援救的浏览器访谈大家的 开荒者博客 中的页面包车型客车时候,一切就盘算妥贴了。断开你的互联网连接,然后刷新一下页面。如若您本身没条件尝试的话,能够看一下这段 演示录像(译者注:需梯子)。

让咱们起头吧

借让你有以下 HTML 页面。那尽管充足基础,但能给您完全思路。

XHTML

<!DOCTYPE html>

1
<!DOCTYPE html>

紧接着,让大家在页面里登记 Service Worker,这里仅成立了该目的。向刚刚的 HTML 里增多以下代码。

JavaScript

<script> // Register the service worker // 注册 service worker if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/service-worker.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); }); } </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
// Register the service worker
// 注册 service worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.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);
   });
}
</script>

下一场,大家需求创建 Service Worker 文件并将其取名叫‘service-worker.js‘。我们打算用这几个 Service Worker 拦截任何互连网央求,以此检查网络的连接性,并依据检查结果向客商重回最适合的情节。

JavaScript

'use strict'; var cacheVersion = 1; var currentCache = { offline: 'offline-cache' + cacheVersion }; const offlineUrl = 'offline-page.html'; this.addEventListener('install', event => { event.waitUntil( caches.open(currentCache.offline).then(function(cache) { return cache.addAll([ './img/offline.svg', offlineUrl ]); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
'use strict';
 
var cacheVersion = 1;
var currentCache = {
  offline: 'offline-cache' + cacheVersion
};
const offlineUrl = 'offline-page.html';
 
this.addEventListener('install', event => {
  event.waitUntil(
    caches.open(currentCache.offline).then(function(cache) {
      return cache.addAll([
          './img/offline.svg',
          offlineUrl
      ]);
    })
  );
});

在地点的代码中,大家在设置 Service Worker 时,向缓存加多了离线页面。假诺大家将代码分为几小块,可看出前几行代码中,笔者为离线页面钦点了缓存版本和UOdysseyL。要是您的缓存有两样版本,那么你只需立异版本号即可轻便地排除缓存。在大约在第 12 行代码,作者向那个离线页面及其财富(如:图片)发出央求。在拿到成功的响应后,我们将离线页面和有关财富丰盛到缓存。

今昔,离线页面已存进缓存了,我们可在急需的时等候检查索它。在同贰个 ServiceWorker 中,我们供给对无网络时回来的离线页面增加相应的逻辑代码。

JavaScript

this.addEventListener('fetch', event => { // request.mode = navigate isn't supported in all browsers // request.mode = naivgate 并不曾获得全部浏览器的扶助 // so include a check for Accept: text/html header. // 由此对 header 的 Accept:text/html 进行核查 if (event.request.mode === 'navigate' || (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) { event.respondWith( fetch(event.request.url).catch(error => { // Return the offline page // 重回离线页面 return caches.match(offlineUrl); }) ); } else{ // Respond with everything else if we can // 重返任何大家能回到的东西 event.respondWith(caches.match(event.request) .then(function (response) { return response || fetch(event.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
this.addEventListener('fetch', event => {
  // request.mode = navigate isn't supported in all browsers
  // request.mode = naivgate 并没有得到所有浏览器的支持
  // so include a check for Accept: text/html header.
  // 因此对 header 的 Accept:text/html 进行核实
  if (event.request.mode === 'navigate' || (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
        event.respondWith(
          fetch(event.request.url).catch(error => {
              // Return the offline page
              // 返回离线页面
              return caches.match(offlineUrl);
          })
    );
  }
  else{
        // Respond with everything else if we can
        // 返回任何我们能返回的东西
        event.respondWith(caches.match(event.request)
                        .then(function (response) {
                        return response || fetch(event.request);
                    })
            );
      }
});

为了测量检验该意义,你能够选用 Chrome 内置的开采者工具。首先,导航到你的页面,然后一旦设置上了 ServiceWorker,就开拓 Network 标签并将节流(throttling)改为 Offline。(译者注:若将节流设置为 Offline 没意义,则可因而关闭网络大概通过360平安警卫禁止 Chrome 访谈网络)

图片 4

假如你刷新页面,你应有能看到相应的离线页面!

图片 5

如若您只想大约地质衡量试该意义而不想写任何代码,那么你能够访问作者已开立好的 demo。其余,上述任何代码能够在 Github repo 找到。

本身清楚用在此案例中的页面很轻巧,但您的离线页面则取决于你协和!纵然你想深刻该案例的源委,你可以为离线页面增加缓存破坏( cache busting),如: 此案例。

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,那您必要先读书这篇文章。

干活规律

经过一段简单的 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,你拜会到专门为您订制的特性化内容,它们是在你在此之前访问网址时由浏览器缓存下来的。它在安装进度中也不会生出其余勤奋,你所急需的只是探望这些网址而已,不像原生应用,还供给客商有多个行使公司的账号工夫设置。瑟维斯worker 同样能够协理大家升高网址的加载速度,因为网址的框架能够被保障地缓存下来,如同原生应用相同。

若是你对 service worker 很感兴趣,想要了然越多内容的话,开荒者 MattGaunt(Chrome的忠实接济者)写了一篇特别详实地 介绍 Service Worker的文章。

打赏协助自个儿翻译越多好小说,感激!

打赏译者

实行阅读

其余,还或许有多少个很棒的离线作用案例。如:Guardian 创设了叁个有着 crossword puzzle(填字游戏)的离线 web 页面 – 由此,固然等待互联网重连时(即已在离线状态下),也能找到一点野趣。我也引入看看 Google Chrome Github repo,它蕴涵了无数见仁见智的 Service Worker 案例 – 当中一部分采取案例也在那!

然则,假诺您想跳过上述代码,只是想大约地因而多少个库来拍卖相关操作,那么小编引入您看看 UpUp。那是一个轻量的脚本,能让您更自在地选用离线作用。

打赏支持自身翻译更加多好小说,感谢!

打赏译者

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

图片 6

打赏扶助我翻译越来越多好作品,多谢!

图片 7

1 赞 收藏 评论

打赏援救小编翻译越多好小说,感谢!

任选一种支付办法

图片 8 图片 9

1 赞 3 收藏 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打探最好实践。

有关我:Erucy

图片 10

曾经的SharePoint喵星技师(临时还挂着微软MVP的名头),今后的Azure/.Net/MongoDB/Cordova/前端程序猿,临时写小说 个人主页 · 作者的篇章 · 46 ·   

图片 11

关于小编:刘健超-J.c

图片 12

前端,在路上... 个人主页 · 笔者的小说 · 19 ·     

图片 13

使用Service Worker

当今大家有了polyfill,并且解决了HTTPS,让大家看看到底怎么用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是否对你的网站启用了。

图片 14

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

您会意识这一个功用能够很有利地在贰个模仿窗口中测验你的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事件。

哪些缓存和再次回到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'
})

如此设计是有理由的,它比XHTiguan的在同源下暗中同意发送凭据,但跨域时吐弃凭据的平整要来得好。fetch的一坐一起更像任何的CO奥迪Q7S央求,比如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

Non-CO凯雷德S暗中同意不帮忙

暗许情状下,从第三方UMuranoL跨域获得三个能源将会倒闭,除非对方帮衬了CO福睿斯S。你能够增多一个non-CO途睿欧S选项到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;" />

图片 15

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

改变URL Hash的Bug

在M40版本中设有三个bug,它会让页面在转移hash的时候变成service worker截止职业。

你能够在此间找到更加多相关的音讯: 

更加多内容

此间有一对皮之不存毛将焉附的文书档案能够参见:

获得救助

借使你遇上麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于我们当下跟进和不择花招扶助你化解难点。

赞 2 收藏 评论

图片 16

版权声明:本文由大奖888-www.88pt88.com-大奖888官网登录发布于前端开发,转载请注明出处:workers规范让在Web App上具备这么些效应成为大概