菜单

Service Worker入门

2019年4月2日 - Bootstrap

Service Worker入门

2015/03/26 · JavaScript
· Service Worker

原版的书文出处: Matt
Gaunt
   译文出处:[w3ctech

原生App拥有Web应用普通所不有所的富离线体验,定时的守口如瓶更新,新闻布告推送等效果。而新的Serviceworkers标准让在Web App上拥有这么些成效成为恐怕。

image

Service Worker 是什么?

一个 service worker
是壹段运转在浏览器后台进度里的本子,它独自于方今页面,提供了那多少个不须要与web页面交互的作用在网页背后悄悄执行的力量。在今后,基于它能够达成新闻推送,静默更新以及地理围栏等劳务,但是最近它首先要负有的职能是阻挠和处理互连网请求,包涵可编制程序的响应缓存管理。

为啥说这么些API是多个丰盛棒的API呢?因为它使得开发者能够支撑特别好的离线体验,它赋予开发者完全控制离线数据的力量。

在service worker建议从前,别的三个提供开发者离线体验的API叫做App
Cache。不过App
Cache有个别局限性,例如它可以很不难地缓解单页应用的难题,可是在多页应用上会很麻烦,而Serviceworkers的出现正是为了消除App Cache的痛点。

下边详细说一下service worker有怎么着须求小心的地方:

越发简的介

2018年开班火遍南北的 PWA 技术诞生景况有负重望,主要源于 safrai
对于这一技术协理不甚美好,不帮忙 mainfest 文件也不帮助
service Worker

service worker 是2个非正规的 web Worker,因而他与页面通讯和 worker
是壹律的,同样不能够访问 DOM。特殊在于她是由事件驱动的持有生命周期的
worker,并且能够阻挡处理页面包车型大巴网络请求(fetch),可以访问 cache
IndexDB

换言之 service Worker
能够让开发者本身决定管理缓存的始末以及版本,为离线弱网环境下的 web
的周转提供了说不定,让 web 在心得上特别靠近 native。

Service Worker的生命周期

瑟维斯 worker拥有二个通通独立于Web页面包车型地铁生命周期。

要让一个service
worker在你的网站上生效,你要求先在您的网页中注册它。注册3个service
worker之后,浏览器会在后台默默运转1个service worker的设置进程。

在设置进度中,浏览器会加载并缓存壹些静态能源。假若全体的文书被缓存成功,service
worker就安装成功了。即使有另外公文加载或缓存战败,那么安装进程就会退步,service
worker就不可能被激活(也即没能安装成功)。即使爆发这么的标题,别担心,它会在下次再品尝安装。

当安装完结后,service
worker的下一步是激活,在这一品级,你仍是能够提高三个service
worker的版本,具体内容大家会在背后讲到。

在激活之后,service
worker将接管全部在大团结管辖域范围内的页面,可是一旦2个页面是刚刚注册了service
worker,那么它那一次不会被接管,到下2回加载页面包车型大巴时候,service
worker才会生效。

当service
worker接管了页面之后,它可能有两种情状:要么被甘休以节本省部存款和储蓄器,要么会处理fetch和message事件,这三个事件分别发出于二个互连网请求现身依旧页面上发送了3个音信。

下图是2个简化了的service worker初次安装的生命周期:

图片 1

非凡意况

safrai 已经于 2017年8月 开始了 service Worker 的开发。

image

日前浏览器PC援救情形如图

境内第叁浏览器帮衬情况

android 设备在 4.4 版本采取 Chromium 作为基本,Chromium 在 40
对于 service worker 帮助。国内浏览器包蕴微信浏览器在内基本已经帮助
service Worker 那为提高体验提供了或然。service workerHTTP2
越发配哦,在现在依照它可以兑现新闻推送,静默更新以及地理围栏等服务。

在我们开始写码以前

从这个类型地址拿到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
打听最好实践。

询问前的刺探

webWorker
fetch
cache
promise

使用Service Worker

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

生命周期

image

Service Workermain.js
实行注册,第①回注册前会开始展览剖析,判断加载的公文是或不是在域名下,协议是还是不是为
HTTPS 的,通过那两点则成功注册。
service Worker 起初进入下3个生命周期状态 installinstall
实现后会触发 service Workerinstall 事件。 如果 install
成功则接下去是 activate状态, 然后那些 service worker
才能接管页面。当事件 active 事件执行到位之后,此时 service Worker
有三种景况,一种是 active,一种是 terminatedactive
是为了工作,terminated则为了节约内部存款和储蓄器。当新的 service Worker 处于
install/waitting 阶段,当前 service Worker 处于
terminated,就会发出交接替换。可能能够透过调用 self.skipWaiting()
方法跳过等待。
被沟通掉的原有的 service WorkerRedundant 阶段,在 install 或者
activating 中断的也会进入 Redundant 阶段。所以1个 Service Worker
脚本的生命周期有如此一些阶段(从左往右):

[图片上传战败…(image-af三cfa-1511157771陆一七)]

如何注册和装置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已经被注册过,浏览器会自行忽略下边的代码。

有3个亟待特别表明的是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是否对你的网站启用了。

图片 2

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

你会发觉这一个职能可以很有益地在二个仿照窗口中测试你的service
worker,那样你可以关闭和重新打开它,而不会影响到你的新窗口。任何创立在模拟窗口中的注册服务和缓存在窗口被关闭时都将熄灭。

Install

install 存在中间态 installing 这一个情景在 main.js
registration挂号对象中能够访问到。

/* In main.js */
// 重写 service worker 作用域到 ./
navigator.serviceWorker.register('./sw.js', {scope: './'}).then(function(registration) {  
    if (registration.installing) {
        // Service Worker is Installing
    }
})

安装时 service Workerinstall
事件被触发,那一般用于拍卖静态财富的缓存

service worker 缓存的静态财富

chrome PWA 演示实例

/* In sw.js */
self.addEventListener('install', function(event) {  
  event.waitUntil(
  // currentCacheName 对应调试工具中高亮位置,缓存的名称
  // 调用 `cache.open` 方法后才可以缓存文件
    caches.open(currentCacheName).then(function(cache) {
    // arrayOfFilesToCache 为存放缓存文件的数组
      return cache.addAll(arrayOfFilesToCache);
    })
  );
});

event.waitUntil() 方法接收1个 promise 对象, 假使那一个 promise
对象 rejectedservice Worker 安装失利,状态变更为
Redundant。关于 cache 相关表明看下文。

瑟维斯 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就安装成功了。假若其余1个文件下载失利,那么安装步骤就会失利。这一个艺术允许你依靠于您本人钦命的兼具能源,但是那表示你供给非常小心地决定哪些文件须要在装置步骤中被缓存。内定了太多的文本的话,就会大增设置退步率。

地点只是贰个简约的事例,你能够在install事件中进行其余操作照旧甚至忽视install事件。

Installed / Waiting

设置到位待正在运维的 service Worker 交接的情况。
Service Worker registration 对象, 我们得以获得这几个场馆

/* In main.js */
navigator.serviceWorker.register('./sw.js').then(function(registration) {  
    if (registration.waiting) {
        // Service Worker is Waiting
    }
})

那是3个唤起用户更新的好机会,也许能够静默更新。

哪些缓存和重回Request

你曾经设置了service worker,你今后得以回来您缓存的呼吁了。

当service
worker被设置成功还要用户浏览了另3个页面恐怕刷新了近来的页面,service
worker将上马接到到fetch事件。上边是1个例子:

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里,大家传入了2个由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只可以被读取三次,所以大家得将它克隆出来,1份发给浏览器,一份发给缓存。

Activating

则状态成为 activating,触发 service workeractive 事件。

/* In sw.js */
self.addEventListener('activate', function(event) {  
  event.waitUntil(
    // Get all the cache names
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        // Get all the items that are stored under a different cache name than the current one
        cacheNames.filter(function(cacheName) {
          return cacheName != currentCacheName;
        }).map(function(cacheName) {
          // Delete the items
          return caches.delete(cacheName);
        })
      ); // end Promise.all()
    }) // end caches.keys()
  ); // end event.waitUntil()
});

install 事件中的 event.waitUntil 方法。当所接收的 promise
reject 那么 serviceWorker 进入 Redundant状态。

什么翻新一个Service Worker

你的service
worker总有亟待立异的那1天。当那1天来到的时候,你必要根据如下步骤来更新:

  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);
          }
        })
      );
    })
  );
});

Actived

activting成功后,这时 service Worker 接管了全部页面状态变成
acticed
其一状态大家得以阻止请求和音讯。

/* In sw.js */

self.addEventListener('fetch', function(event) {  
  // Do stuff with fetch events
});

self.addEventListener('message', function(event) {  
  // Do stuff with postMessages received from document
});

拍卖边界和填坑

这一节内容相比较新,有触目皆是待定细节。希望这一节非常的慢就不须求讲了(因为标准会处理这几个难题——译者注),然而未来,这个内容照旧应当被提一下。

Redundant

service Workerinstall active进程中处错误也许,被新的
service Worker 替换状态会成为 Redundant

只假诺后壹种情形,则该 worker 依旧控制那个页面。

值得注意的是已经 installservice worker
页面关闭后再打开不会触发 install 事件,然则会再也注册。越来越多参考小说
研讨 Service Worker
「生命周期」

比方设置退步了,未有很优雅的办法赢得通报

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

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

呼吁处理

处于 actived 阶段的 service Worker 能够阻挡页面发出的
fetch,也得以生出fetch伸手,能够将呼吁和响应缓存在
cache里,也足以将 responsecache 中取出。

fetch()方今仅协理瑟维斯 Workers

fetch马上援救在页面上选拔了,不过当前的Chrome达成,它还只扶助service
worker。cache
API也即将在页面上被帮助,但是近来甘休,cache也还不得不在service
worker中用。

缓存使用政策

据此能够依据使用的景色,使用缓存的 response
给到页面减弱请求及时响应,亦也许将呼吁重临的结果更新到缓存,在采纳离线时重回给页面。那便是以下的三种策略。

  1. 网络优先: 从互连网得到, 战败或许逾期再品尝从缓存读取
  2. 缓存优先: 从缓存获取,
    缓存插叙不到再尝试从网络抓取,在上文中的代码块就是该种策略的贯彻。
  3. 最快: 同时询问缓存和互连网, 重临起始得到的
  4. 仅限网络: 仅从互联网获取
  5. 仅限缓存: 仅从缓存获取

fetch()的暗中同意参数

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

JavaScript

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

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

如此设计是有理由的,它比XH宝马X5的在同源下私下认可发送凭据,但跨域时放弃凭据的平整要来得好。fetch的一言一动更像任何的CO索罗德S请求,例如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

示例

fetch 基于stream 的 ,因此 response & request
一旦被消费则不能复苏,所以这边在缓存的时候供给运用 clone
方法在消费前复制一份。

self.addEventListener('fetch', function(event) {
// 只对 get 类型的请求进行拦截处理
  if (event.request.method !== 'GET') {
    console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
    return;
  }
  event.respondWith(
  // 缓存中匹配请求
    caches.match(event.request)
      .then(function(response) {
        if (response) {
          return response;
        }

        // 因为 event.request 流已经在 caches.match 中使用过一次,
        // 那么该流是不能再次使用的。我们只能得到它的副本,拿去使用。
        var fetchRequest = event.request.clone();

        // fetch 的通过信方式,得到 Request 对象,然后发送请求
        return fetch(fetchRequest).then(
          function(response) {
            // 检查是否成功
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

            // 如果成功,该 response 一是要拿给浏览器渲染,而是要进行缓存。
            // 不过需要记住,由于 caches.put 使用的是文件的响应流,一旦使用,
            // 那么返回的 response 就无法访问造成失败,所以,这里需要复制一份。
            var responseToCache = response.clone();

            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });

            return response;
          }
        );
      })
    );
});

Non-CO途达S暗中同意不帮衬

私下认可情况下,从第2方UOdysseyL跨域得到三个能源将会破产,除非对方帮衬了CO凯雷德S。你能够添加贰个non-COEvoqueS选项到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;

Register 时机

service Worker 将深化对 CPU
时间和内部存储器的争用,从而影响浏览器渲染以及网页的互相。Chrome 团队的开发者
杰夫 Posnick 实践申明在突显动画时期注册 service Worker
会导致低端移动设备出现卡顿,由此在那种场地下延后注册或等更好的用户体验。

//Bad
window.addEventListener('DOMContentLoaded', function() {
    navigator.serviceWorker.register('/sw.js').then(function(registration) {

    }).catch(function(err) {

    }); 
  });


// Good
if ('serviceWorker' in navigator) {
// 判断浏览器支持情况
  window.addEventListener('load', function() {
  // 页面所有资源加载完成后注册
    navigator.serviceWorker.register('/service-worker.js');
  });
}

不过当您利用 clients.claim()service Worker 控制全体

拍卖响应式图片

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

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

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

正如好的方案是二或三,因为假如把持有的图样都给下载下来存着有点浪费内部存款和储蓄器。

若果你将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" />

万一大家在2个二x的体现形式下,浏览器会下载image-二x.png,假诺大家离线,你能够读取此前缓存并再次来到image-src.png替代,若是以前它曾经被缓存过。就算如此,由于现行反革命的形式是二x,浏览器会把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;" />

图片 3

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

install 事件中静态能源缓存

service Workerinstall
事件中缓存文件进度中,当在那之中一个文书加载退步,则 install
战败。因而得以对要缓存的公文进行分级,一定要加载的,和允许加载战败的,对于同意加载失败的文书。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('mygame-core-v1').then(function(cache) {
    // 不稳定文件或大文件加载
      cache.addAll(
        //...
      );
      // 稳定文件或小文件加载
      return cache.addAll(
        // core assets & levels 1-10
      );
    })
  );
});

改变URL Hash的Bug

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

您能够在此间找到更加多相关的新闻: https://code.google.com/p/chromium/issues/detail?id=433708

拍卖请求中离线情状

service Worker 发送请求时,捕获很是,并再次来到页面多个 response
布告页面也许离线。

function unableToResolve () {
  /* 
    当代码执行到这里,说明请求无论是从缓存还是走网络,都无法得到答复,这个时机,我们可以返回一个相对友好的页面,告诉用户,你可能离线了。
  */
  console.log('WORKER: fetch request failed in both cache and network.');
  return new Response('<h1>Service Unavailable</h1>', {
    status: 503,
    statusText: 'Service Unavailable',
    headers: new Headers({
      'Content-Type': 'text/html'
    })
  });
}
fetch(event.request).then(fetchedFromNetwork, unableToResolve).catch(unableToResolve);

越来越多内容

此间有壹些连锁的文书档案能够参见:https://jakearchibald.github.io/isserviceworkerready/resources.html

引入开关机制

开关是在饿了么实践经验里建议降级方案,通过向后端请求3个是还是不是降级的接口,要是降级则裁撤掉已经注册的service Worker。这里要专注不要缓存那几个开关请求。为了方便难点排查,能够设置一个debug 格局(在 url 添加有个别字符)。

获得扶助

比方您遇上麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于我们立即跟进和尽恐怕援助你化解难题。

赞 2 收藏
评论

图片 4

荒谬监察和控制

self.addEventListener('error', event => {
  // 上报错误信息
  // 常用的属性:
  // event.message
  // event.filename
  // event.lineno
  // event.colno
  // event.error.stack
})
// 捕获 promise 错误
self.addEventListener('unhandledrejection', event => {
  // 上报错误信息
  // 常用的属性:
  // event.reason
})

那八个事件都只能在 worker 线程的 initial
生命周期里登记。(不然会破产,控制台可观看警告)

谷歌 开发工具助力 service worker 开发

Google 提供了 sw-toolboxsw-precache 三个工具方便高效生成
service-worker.js 文件:

更多[参照小说]([PWA 入门: 通晓和创办 Service Worker 脚本])

注意事项

参考

MDN
Service Worker
lifecycle

service worker
note

update service
worker

chrom service worker
sample

PWA 入门: 精晓和创办 Service Worker
脚本

PWA
在饿了么的实践经验

相关文章

发表评论

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

网站地图xml地图