创制一个格外简单的离线页面,worker完毕加快

迈向PWA!利用serviceworker的离线访问方式

2017/02/08 · JavaScript
· PWA

正文作者: 伯乐在线 –
pangjian
。未经小编许可,禁止转载!
欢迎参与伯乐在线 专栏撰稿人。

微信小程序来了,可以行使WEB技术在微信打造一个具备Native应用经验的行使,业界非常看好那种格局。可是你们可能不了然,谷歌早已有接近的统筹,甚至层次更高。那就是PWA(渐进式增强WEB应用)。
PWA有以下三种特色:

  • Installablity(可安装性)
  • App Shell
  • Offline(离线能力)
  • Re-engageable(推送公告能力)

拥有这一个特色都是“优雅降级、渐进增强的”,给帮助的装置更好的体会,不援助的配备也不会更差。那就和微信小程序那种蹩脚设计的根本不一样之处。

本博客也在向着PWA的取向迈进,第一步我选用了Offline,也就是离线能力。能够让客户在没有网络连接的时候仍能选取部分服务。那一个能力运用了ServiceWorker技术。

兑现思路就是,利用service
worker,另起一个线程,用来监听所有网络请求,讲曾经呼吁过的数量放入cache,在断网的情状下,直接取用cache里面的资源。为呼吁过的页面和图片,显示一个默许值。当有网络的时候,再重复从服务器更新。
金沙澳门官网 1
代码那里就不贴了,未来可能会专门写一篇来详细介绍Service(Service)Worker,有趣味的可以一向参考源码。
注册起来也丰裕有利于

JavaScript

// ServiceWorker_js (function() { ‘use strict’;
navigator.serviceWorker.register(‘/sw.js’, {scope:
‘/’}).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
10
11
12
// ServiceWorker_js
(function() {
    ‘use strict’;
    navigator.serviceWorker.register(‘/sw.js’, {scope: ‘/’}).then(function(registration) {
      // Registration was successful
      console.log(‘ServiceWorker registration successful with scope: ‘, registration.scope);
    }).catch(function(err) {
      // registration failed 🙁
      console.log(‘ServiceWorker registration failed: ‘, err);
    });
 
})();

此处需求专注的是,sw.js所在的目录要当先它的决定范围,也就是scope。我把sw.js座落了根目录来控制总体目录。

接下去看看大家的末段效果呢,你也可以在温馨的浏览器下断网尝试一下。当然有一些浏览器近日还不支持,比如知名的Safari。

运用 瑟维斯(Service) worker 创设一个非凡简单的离线页面

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

本文由 伯乐在线 –
刘健超-J.c
翻译,艾凌风
校稿。未经许可,禁止转发!
英文出处:Dean
Hume。欢迎加入翻译组。

让我们想像以下场景:大家那儿在一辆通往农村的轻轨上,用移动装备瞧着一篇很棒的稿子。与此同时,当你点击“查看更加多”的链接时,火车忽然进入了隧道,导致运动装备失去了网络,而
web 页面会显示出类似以下的始末:

金沙澳门官网 2

那是一对一令人心寒的感受!幸运的是,web
开发者们能因此一些新特征来革新那类的用户体验。我多年来一贯在折腾 瑟维斯(Service)(Service)Workers,它给 web 带来的无尽可能性总能给本人惊喜。Service Workers
的绝妙特质之一是同意你检测网络请求的现象,并让你作出相应的响应。

在那篇作品里,我打算用此特性检查用户的当下网络连接意况,即使没连接则赶回一个特级不难的离线页面。固然那是一个可怜基础的案例,但它能给你带来启迪,让您精通启动并运行该特性是何其的简短!如若你没了解过
Service Worker,我指出您看看此 Github
repo,了然愈来愈多相关的新闻。

在此案例先导前,让大家先简单地看望它的劳作流程:

  1. 在用户首次访问我们的页面时,我们会安装 瑟维斯(Service)(Service)Worker,并向浏览器的缓存添加我们的离线 HTML 页面
  2. 下一场,假设用户打算导航到另一个 web
    页面(同一个网站下),但此刻已断网,那么大家将赶回已被缓存的离线
    HTML 页面
  3. 而是,倘诺用户打算导航到其它一个 web
    页面,而此刻网络已一连,则能照常浏览页面

动用瑟维斯(Service)(Service) worker完毕加速/离线访问静态blog网站

2017/02/19 · JavaScript
· Service Worker

初稿出处: Yang
Bo   

近来很盛行基于Github
page和markdown的静态blog,卓殊适合技术的思想和习惯,针对不一致的言语都有一部分名特优的静态blog系统出现,如Jekyll/Ruby,Pelican/Python,Hexo/NodeJs,由于静态内容的特点非凡适合做缓存来加速页面的访问,就采用Service
worker
来促成加速,结果是除了PageSpeed,CDN那几个大规模的服务器和网络加速之外,通过客户端落成了更好的拜会体验。

Service Worker入门

2015/03/26 · JavaScript
· Service Worker

原稿出处: Matt
Gaunt   译文出处:创制一个格外简单的离线页面,worker完毕加快。[w3ctech

  • 十年踪迹]()   

原生App拥有Web应用普通所不享有的富离线体验,定时的沉默更新,新闻布告推送等职能。而新的Serviceworkers标准让在Web App上享有那几个效应成为可能。

离线有缓存情形

金沙澳门官网 3

让大家初阶吧

若果你有以下 HTML 页面。那即使分外基础,但能给您完全思路。

XHTML

<!DOCTYPE html>

1
<!DOCTYPE html>

随即,让我们在页面里登记 瑟维斯(Service)(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(‘Service(Service)Worker 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(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)(Service) Worker
时,向缓存添加了离线页面。就算大家将代码分为几小块,可寓方今几行代码中,我为离线页面指定了缓存版本和URL。如果你的缓存有两样版本,那么您只需立异版本号即可简单地铲除缓存。在大概在第
12
行代码,我向那一个离线页面及其资源(如:图片)发出请求。在获取成功的响应后,大家将离线页面和连锁资源丰富到缓存。

今昔,离线页面已存进缓存了,大家可在必要的时候检索它。在同一个 ServiceWorker 中,我们需求对无网络时回来的离线页面添加相应的逻辑代码。

JavaScript

this.add伊芙ntListener(‘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),如:
此案例。

加紧/离线访问只需三步

  • 首页添加注册代码

JavaScript

<script> if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’); } </script>

1
2
3
4
5
<script>
if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’);
}
</script>
  • 复制代码

将保存到你的网站根目录下

  • 修改不缓存域名列表及离线状态页面

在你的sw.js中修改

JavaScript

const ignoreFetch = [ /https?:\/\/cdn.bootcss.com\//,
/https?:\/\/static.duoshuo.com\//,
/https?:\/\/www.google-analytics.com\//,
/https?:\/\/dn-lbstatics.qbox.me\//, ];

1
2
3
4
5
6
const ignoreFetch = [
  /https?:\/\/cdn.bootcss.com\//,
  /https?:\/\/static.duoshuo.com\//,
  /https?:\/\/www.google-analytics.com\//,
  /https?:\/\/dn-lbstatics.qbox.me\//,
];

打开Chrome Dev Tools->Source,看看自己的blog都引用了哪些第三方资源,逐个加到忽略列表里。

金沙澳门官网 6

在根目录下添加offline.html,在并未网络且缓存中也没有时选用,效果如下:

金沙澳门官网 7

在根目录下添加offline.svg,在无网络时图片资源请求再次来到该公文。

Service Worker 是什么?

一个 service worker
是一段运行在浏览器后台进度里的台本,它独自于方今页面,提供了这一个不需求与web页面交互的功用在网页背后悄悄执行的能力。在将来,基于它可以兑现消息推送,静默更新以及地理围栏等劳动,不过近日它首先要有所的功力是阻挡和处理网络请求,包蕴可编程的响应缓存管理。

干什么说那么些API是一个分外棒的API呢?因为它使得开发者可以援救尤其好的离线体验,它赋予开发者完全控制离线数据的能力。

在service worker提议从前,其它一个提供开发者离线体验的API叫做App
Cache。然则App
Cache有些局限性,例如它可以很不难地解决单页应用的题目,不过在多页应用上会很劳累,而瑟维斯(Service)workers的面世正是为了缓解App Cache的痛点。

下边详细说一下service worker有哪些须要小心的地点:

  • 它是JavaScript
    Worker,所以它不可能平素操作DOM。不过service
    worker可以透过postMessage与页面之间通讯,把音信文告给页面,要是必要的话,让页面自己去操作DOM。
  • Serviceworker是一个可编程的网络代理,允许开发者控制页面上处理的网络请求。
  • 在不被运用的时候,它会友善终止,而当它再也被用到的时候,会被再一次激活,所以你无法依靠于service
    worker的onfecth和onmessage的处理函数中的全局状态。倘诺您想要保存一些持久化的音讯,你可以在service
    worker里使用IndexedDB API。
  • Serviceworker大批量使用promise,所以一旦你不领会哪些是promise,这您须要先读书这篇文章。

离线无缓存情形

会展现一个默许的页面

金沙澳门官网 8

-EOF-

打赏协理自己写出越多好文章,谢谢!

打赏小编

展开阅读

别的,还有多少个很棒的离线效率案例。如:Guardian 构建了一个富有 crossword
puzzle(填字游戏)的离线
web 页面 –
因而,即便等待网络重连时(即已在离线状态下),也能找到一点乐趣。我也引进看看
Google Chrome Github
repo,它包蕴了诸多见仁见智的
Service Worker 案例 – 其中有些使用案例也在那!

可是,假设您想跳过上述代码,只是想大致地经过一个库来处理有关操作,那么我引进你看看
UpUp。那是一个轻量的本子,能让您更自在地使用离线成效。

打赏扶助自己翻译越来越多好文章,谢谢!

打赏译者

加快效果

首页加速后,网络请求从16降为1,加载时间从2.296s降为0.654s,得到了瞬间加载的结果。

金沙澳门官网 9

基于webpagetest

查看测试结果

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

金沙澳门官网 10

打赏帮助我写出越来越多好文章,谢谢!

任选一种支付办法

金沙澳门官网 11
金沙澳门官网 12

1 赞 1 收藏
评论

打赏帮衬我翻译越来越多好作品,谢谢!

任选一种支付办法

金沙澳门官网 13
金沙澳门官网 14

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问询最佳实践。

至于作者:pangjian

金沙澳门官网 15

庞健,金融IT男。
个人主页 ·
我的稿子 ·
5 ·
  

金沙澳门官网 16

关于作者:刘健超-J.c

金沙澳门官网 17

前端,在路上…
个人主页 ·
我的小说 ·
19 ·
    

金沙澳门官网 18

什么是 Service worker

金沙澳门官网 19

如上图,Service
worker

是一种由Javascript编写的浏览器端代理脚本,位于你的浏览器和服务器之间。当一个页面注册了一个
Service
worker
,它就可以注册一名目繁多事件处理器来响应如网络请求和音信推送那么些事件。Service
worker

可以被用来保管缓存,当响应一个网络请求时得以配备为回去缓存仍旧从网络获得。由于Service
worker

是根据事件的,所以它只在拍卖这几个事件的时候被调入内存,不用担心常驻内存占用资源导致系统变慢。

使用Service Worker

前天大家有了polyfill,并且搞定了HTTPS,让大家看看到底怎么用service
worker。

瑟维斯(Service)(Service) worker生命周期

金沙澳门官网 20

Service
worker

为网页添加一个近似于APP的生命周期,它只会响应系统事件,固然浏览器关闭时操作系统也足以提醒Service
worker
,这一点极度重要,让web
app与native app的力量变得近乎了。

Service
worker
在Register时会触发Install事件,在Install时可以用来预先获取和缓存应用所需的资源并安装每个文件的缓存策略。

一旦Service
worker
高居activated状态,就可以完全控制应用的资源,对网络请求举行检查,修改网络请求,从网络上得到并回到内容可能重回由已设置的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是否对你的网站启用了。

金沙澳门官网 21

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

您会发觉那么些功效可以很便宜地在一个模仿窗口中测试你的service
worker,那样您可以关闭和重复打开它,而不会潜移默化到您的新窗口。任何创建在模仿窗口中的注册服务和缓存在窗口被关门时都将化为乌有。

瑟维斯(Service)(Service) worker的支配从第二次页面访问开头

在首次加载页面时,所有资源都是从网络载的,Service
worker

在首次加载时不会收获控制网络响应,它只会在再而三访问页面时起效果。

金沙澳门官网 22

页面首次加载时成功install,并进入idle状态。

金沙澳门官网 23

页面第二次加载时,进入activated状态,准备处理所有的风波,同时
浏览器会向服务器发送一个异步 请求来检查Service
worker
我是或不是有新的版本,构成了Service
worker
的更新机制。

金沙澳门官网 24

Service
worker
拍卖完所有的轩然大波后,进入idle状态,最后进入terminated状态资源被释放,当有新的风浪爆发时再一次被调用。

瑟维斯(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事件。

特点

  • 浏览器

谷歌 Chrome,Firefox,Opera以及国内的各类双核浏览器都帮助,但是 safari
不协助,那么在不支持的浏览器里Service
worker
不工作。

  • https

网站必须启用https来保障使用Service
worker
金沙澳门官网 ,页面的安全性,开发时localhost默许认为是安全的。

  • non-block

Service
worker

中的 Javascript 代码必须是非阻塞的,因为 localStorage
是阻塞性,所以不该在 Service(Service) Worker 代码中选取 localStorage。

  • 单独的施行环境

Service
worker
运作在自己的全局环境中,平日也运行在大团结单独的线程中。

  • 没有绑定到一定页面

service work能控制它所加载的全部范围内的资源。

  • 不可以操作DOM

跟DOM所处的条件是互相隔离的。

金沙澳门官网 25

  • 尚无浏览页面时也可以运行

收受系统事件,后台运行

  • 事件驱动,必要时运行,不要求时就停下

按需实践,只在急需时加载到内存

  • 可升级

举行时会异步获取最新的版本

什么样缓存和再次来到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)(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);
          }
        })
      );
    })
  );
});

Cache

网页缓存有成百上千,如HTTP缓存,localStorage,sessionStorage和cacheStorage都足以灵活搭配进行缓存,但操作孝庄文皇后繁琐,直接运用更高级Service
worker

–本文的主人。

处理边界和填坑

这一节内容比较新,有过多待定细节。希望这一节很快就不须求讲了(因为标准会处理那个问题——译者注),可是现在,那个情节依旧应当被提一下。

添加Service worker入口

在web app的首页添加以下代码

JavaScript

<script> if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’); } </script>

1
2
3
4
5
<script>
if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’);
}
</script>

假设浏览器匡助serviceWorker就登记它,不襄助仍旧正常浏览,没有Service
worker
所提供的加强成效。

瑟维斯(Service)(Service) worker控制范围:
简易景况下,将sw.js身处网站的根目录下,那样Service
worker
能够操纵网站有着的页面,,同理,如果把sw.js放在/my-app/sw.js那么它不得不控制my-app目录下的页面。
sw.js放在/js/目录呢?更好的目录结构和限量控制呢?
在登记时指定js地点并安装限制。

JavaScript

navigator.serviceWorker.register(‘/js/sw.js’, {scope:
‘/sw-test/’}).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
navigator.serviceWorker.register(‘/js/sw.js’, {scope: ‘/sw-test/’}).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);
    });

假定设置失利了,没有很优雅的主意获取通报

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

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

Service worker实现

监听五个事件:

JavaScript

self.addEventListener(‘install’, onInstall);
self.addEventListener(‘fetch’, onFetch);
self.addEventListener(“activate”, onActivate);

1
2
3
self.addEventListener(‘install’, onInstall);
self.addEventListener(‘fetch’, onFetch);
self.addEventListener("activate", onActivate);

fetch()近期仅接济瑟维斯(Service) Workers

fetch即刻帮助在页面上使用了,可是当前的Chrome完成,它还只扶助service
worker。cache
API也就要在页面上被协理,可是近来甘休,cache也还不得不在service
worker中用。

install

JavaScript

////////// // Install ////////// function onInstall(event) {
log(‘install event in progress.’); event.waitUntil(updateStaticCache());
} function updateStaticCache() { return caches
.open(cacheKey(‘offline’)) .then((cache) => { return
cache.addAll(offlineResources); }) .then(() => { log(‘installation
complete!’); }); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//////////
// Install
//////////
function onInstall(event) {
  log(‘install event in progress.’);
  event.waitUntil(updateStaticCache());
}
function updateStaticCache() {
  return caches
    .open(cacheKey(‘offline’))
    .then((cache) => {
      return cache.addAll(offlineResources);
    })
    .then(() => {
      log(‘installation complete!’);
    });
}

install时将所有符合缓存策略的资源拓展缓存。

fetch()的默许参数

当您使用fetch,缺省地,请求不会带上cookies等证据,要想带上的话,必要:

JavaScript

fetch(url, { credentials: ‘include’ })

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

如此设计是有理由的,它比XHR的在同源下默许发送凭据,但跨域时废弃凭据的平整要来得好。fetch的一坐一起更像任何的CORS请求,例如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

fetch

JavaScript

//////// // Fetch //////// function onFetch(event) { const request =
event.request; if (shouldAlwaysFetch(request)) {
event.respondWith(networkedOrOffline(request)); return; } if
(shouldFetchAndCache(request)) {
event.respondWith(networkedOrCached(request)); return; }
event.respondWith(cachedOrNetworked(request)); }
onFetch做为浏览器网络请求的代理,依照须求再次来到网络或缓存内容,假设得到了网络内容,再次回到网络请求时还要进行缓存操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
////////
// Fetch
////////
function onFetch(event) {
  const request = event.request;
  if (shouldAlwaysFetch(request)) {
    event.respondWith(networkedOrOffline(request));
    return;
  }
  if (shouldFetchAndCache(request)) {
    event.respondWith(networkedOrCached(request));
    return;
  }
  event.respondWith(cachedOrNetworked(request));
}
onFetch做为浏览器网络请求的代理,根据需要返回网络或缓存内容,如果获取了网络内容,返回网络请求时同时进行缓存操作。

Non-CORS默许不协理

默许景况下,从第三方URL跨域得到一个资源将会战败,除非对方援救了CORS。你可以增加一个non-CORS选项到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.’);
});

activate

JavaScript

/////////// // Activate /////////// function onActivate(event) {
log(‘activate event in progress.’); event.waitUntil(removeOldCache()); }
function removeOldCache() { return caches .keys() .then((keys) => {
return Promise.all( // We return a promise that settles when all
outdated caches are deleted. keys .filter((key) => { return
!key.startsWith(version); // Filter by keys that don’t start with the
latest version prefix. }) .map((key) => { return caches.delete(key);
// Return a promise that’s fulfilled when each outdated cache is
deleted. }) ); }) .then(() => { log(‘removeOldCache completed.’); });
}

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
///////////
// Activate
///////////
function onActivate(event) {
  log(‘activate event in progress.’);
  event.waitUntil(removeOldCache());
}
function removeOldCache() {
  return caches
    .keys()
    .then((keys) => {
      return Promise.all( // We return a promise that settles when all outdated caches are deleted.
        keys
         .filter((key) => {
           return !key.startsWith(version); // Filter by keys that don’t start with the latest version prefix.
         })
         .map((key) => {
           return caches.delete(key); // Return a promise that’s fulfilled when each outdated cache is deleted.
         })
      );
    })
    .then(() => {
      log(‘removeOldCache completed.’);
    });
}

在activate时依据version值来删除过期的缓存。

fetch()不根据30x重定向规范

糟糕,重定向在fetch()中不会被触发,这是时下版本的bug;

管理 Service worker

拍卖响应式图片

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;" />

金沙澳门官网 26

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

一定网站

  1. Google Chrome

Developer Tools->Application->Service Workers

金沙澳门官网 27

在此地还有三个要命实用的复选框:

  • Offline

萧规曹随断网状态

  • Update on reload
    加载时更新
  • Bypass for network
    连日来利用网络内容
  1. Firefox

只有在Settings里有一个可以在HTTP环境中应用Service
worker
的选项,适应于调试,没有单独网站下的Service
worker
管理。

金沙澳门官网 28

  1. Opera及别的双核浏览器同谷歌(Google) Chrome
    假设看到八个一律范围内的多个Service
    worker
    ,说明Service
    woker
    更新后,而原有Service
    worker
    还未曾被terminated。

改变URL Hash的Bug

在M40版本中留存一个bug,它会让页面在变更hash的时候造成service
worker截止工作。

您可以在那边找到越多相关的音信: 

浏览器全局

看看你的浏览器里都有如何Service worker已经存在了

  1. Google Chrome

在地址栏里输入:

JavaScript

chrome://serviceworker-internals/

1
chrome://serviceworker-internals/

可以观望曾经有24个Serviceworker了,在那边可以手动Start让它工作,也可以Unregister卸载掉。

金沙澳门官网 29

  1. Firefox

有三种方法进入Service
worker
管住界面来手动Start或unregister。

  • 菜单栏,Tool->Web Developer->Service workers
  • 地点栏中输入

JavaScript

about:debugging#workers

1
about:debugging#workers

金沙澳门官网 30

  1. Opera及任何双核浏览器同谷歌(Google) Chrome

更加多内容

此地有一部分有关的文档可以参见:

更多

TODO:

  • Service
    workers
    的更新须求手动编辑version,每趟发布新文章时索要编制。
  • 使用AMP让页面渲染速度直达最高。

取得赞助

假若你遇见麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于大家马上跟进和不择手段协理您解决问题。

赞 2 收藏
评论

金沙澳门官网 31

Ref links

Service Worker Cookbook

Is service worker
ready?

Chrome service worker status
page

Firefox service worker status
page

MS Edge service worker status
page

WebKit service worker status
page

1 赞 2 收藏
评论

金沙澳门官网 32

发表评论

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

网站地图xml地图