菜单

Service Worker 从入门到进阶

2019年4月16日 - Html/Html5

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有些局限性,例如它能够很轻松地化解单页应用的主题材料,不过在多页应用上会很麻烦,而瑟维斯workers的产出便是为了缓解App Cache的痛点。

下边详细说一下service worker有怎么着要求注意的地点:

特别简的介

2018年始于火遍南北的 PWA 本事诞生境况有负重望,重要缘于 safrai
对于这一手艺援助不甚美好,不帮助 mainfest 文件也不帮忙
service Worker

service worker 是二个非同一般的 web Worker,由此她与页面通讯和 worker
是一样的,同样无法访问 DOM。特殊在于她是由事件驱动的持有生命周期的
worker,并且能够阻挡处理页面包车型地铁网络请求(fetch),能够访问 cache
IndexDB

换言之 service Worker
能够让开拓者自个儿说了算管理缓存的始末以及版本,为离线弱网环境下的 web
的周转提供了说不定,让 web 在体会上越发靠近 native。

Service Worker的生命周期

Service worker具有1个全然独立于Web页面包车型客车生命周期。

要让一个service
worker在你的网址上生效,你须要先在您的网页中注册它。注册三个service
worker之后,浏览器会在后台默默运行3个service worker的安装进程。

在安装进程中,浏览器会加载并缓存1些静态财富。要是具备的文本被缓存成功,service
worker就设置成功了。假如有任何公文加载或缓存失利,那么安装进度就会停业,service
worker就不可能被激活(也即没能安装成功)。借使发生如此的难题,别顾忌,它会在下次再尝试安装。

当安装到位后,service
worker的下一步是激活,在这一品级,你还足以进级二个service
worker的本子,具体内容我们会在后头讲到。

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

当service
worker接管了页面之后,它可能有二种意况:要么被终止以节约内部存款和储蓄器,要么会处理fetch和message事件,那三个事件分别发生于一个互联网请求出现如故页面上发送了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的,所以它是1个一矢双穿的原状实验田。

假如您想要让您的server扶助HTTPS,你须求为你的server得到2个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 阶段。所以一个 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已经被登记过,浏览器会活动忽略上边的代码。

有三个急需特地表达的是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 相关表达看下文。

Service Worker的安装步骤

在页面上达成登记手续之后,让我们把注意力转到service
worker的本子里来,在那其间,大家要大功告成它的设置步骤。

在最基本的事例中,你须求为install事件定义1个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得到3个promise并采用它来博取安装开支的时辰以及是或不是安装成功。

壹旦具备的文本都被缓存成功了,那么service
worker就设置成功了。假设别的三个文件下载战败,那么安装步骤就会退步。那么些法子允许你依靠于您自身钦赐的具有财富,可是那表示你要求至十分的小心地调控哪些文件需求在设置步骤中被缓存。钦定了太多的文书的话,就会增添设置退步率。

地点只是3个简便的例证,你能够在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被设置成功还要用户浏览了另三个页面或许刷新了方今的页面,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里,大家传入了2个由caches.match产生的promise.caches.match
查找request中被service worker缓存命中的response。

假定我们有二个命中的response,大家重回被缓存的值,不然大家回来2个实时从互连网请求fetch的结果。那是1个相当轻松的例证,使用全部在install步骤下被缓存的财富。

1经我们想要增量地缓存新的请求,大家得以由此拍卖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. 充裕3个callback到fetch请求的 .then 方法中
  2. 要是我们收获了二个response,大家进行如下的反省:
    1. 确认保障response是实用的
    2. 反省response的动静是不是是200
    3. 确认保证response的花色是basic,那代表请求小编是同源的,非同源(即跨域)的伸手也无法被缓存。
  3. 设若大家经过了检查,clone本条请求。这么做的来由是假设response是1个Stream,那么它的body只好被读取3次,所以大家得将它克隆出来,壹份发给浏览器,一份发给缓存。

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中实行3个管理cache的操作。因为您会须要破除掉以前旧的数量。大家在activate而不是install的时候施行这几个操作是因为只要大家在install的时候立即推行它,那么依旧在运作的旧版本的数额就坏了。

前面大家只使用了2个缓存,叫做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()最近仅帮助Service 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’
})

那般设计是有理由的,它比XHLAND的在同源下暗中同意发送凭据,但跨域时吐弃凭据的平整要来得好。fetch的行事更像任何的CO昂科威S请求,例如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

示例

fetch 基于stream 的 ,因此 response & request
壹旦被消费则不可能恢复,所以那里在缓存的时候要求利用 clone
方法在消费前复制1份。

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-COCRUISERS暗许不援救

暗中同意情状下,从第二方U中华VL跨域获得1个能源将会停业,除非对方帮忙了CO瑞鹰S。你能够增加二个non-COHavalS选项到Request去防止失利。代价是这么做会回来1个“不透明”的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. 安装单一的high-res版本图片

正如好的方案是贰或三,因为1旦把全数的图片都给下载下来存着有点浪费内部存款和储蓄器。

只要你将low-res版本在install的时候缓存了,然后在页面加载的时候你想要尝试从网络上下载high-res的本子,可是壹旦high-res版本下载失利以来,就依旧用low-res版本。那些想法很好也值得去做,不过有3个标题:

即便大家有上面二种图片:

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-二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版本中设有三个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

引进开关机制

按钮是在饿了么实施经验里建议降级方案,通过向后端请求1个是不是降级的接口,假设降级则打消掉已经注册的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地图