菜单

Service Worker入门

2019年4月18日 - Ajax

Service Worker入门

2015/03/26 · JavaScript
· Service Worker

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

原生App具有Web应用普通所不富有的富离线体验,定期的敦默寡言更新,音讯通知推送等功用。而新的Serviceworkers标准让在Web App上有着那些作用成为或然。

image

Service Worker 是什么?

3个 service worker
是一段运营在浏览器后台进度里的脚本,它独自于近来页面,提供了那多少个不须要与web页面交互的功力在网页背后悄悄实践的技艺。在今后,基于它能够兑现新闻推送,静默更新以及地理围栏等服务,不过当前它首先要享有的效应是阻挠和拍卖网络请求,包涵可编程的响应缓存管理。

为啥说那一个API是三个至相当的赞的API呢?因为它使得开垦者能够扶助特别好的离线体验,它赋予开垦者完全调节离线数据的力量。

在service worker提议以前,别的一个提供开采者离线体验的API叫做App
Cache。但是App
Cache某些局限性,例如它能够很轻易地缓解单页应用的主题素材,但是在多页应用上会很辛勤,而Serviceworkers的产出正是为了化解App Cache的痛点。

下面详细说一下service worker有如何须求注意的地点:

越发简的介

二〇一八年伊始火遍南北的 PWA 本事诞生处境有负重望,首要根源 safrai
对于这一本事援助不甚理想,不辅助 mainfest 文件也不支持
service Worker

service worker 是1个非常的 web Worker,由此她与页面通信和 worker
是同1的,同样不能够访问 DOM。特殊在于他是由事件驱动的具有生命周期的
worker,并且能够阻碍处理页面包车型大巴网络请求(fetch),可以访问 cache
IndexDB

换言之 service Worker
能够让开采者本人主宰管理缓存的始末以及版本,为离线弱网环境下的 web
的周转提供了说不定,让 web 在感受上尤其靠近 native。

Service Worker的生命周期

Service worker具备一个完全部独用立于Web页面包车型大巴生命周期。

要让1个service
worker在您的网址上生效,你需要先在你的网页中注册它。注册3个service
worker之后,浏览器会在后台默默运营三个service worker的装置进度。

在装置进程中,浏览器会加载并缓存1些静态财富。假若具有的文本被缓存成功,service
worker就设置成功了。若是有任何公文加载或缓存战败,那么安装进程就会倒闭,service
worker就不可能被激活(也即没能安装成功)。借使发生如此的难点,别忧郁,它会在下次再品尝安装。

当安装到位后,service
worker的下一步是激活,在这一等第,你还足以荣升3个service
worker的本子,具体内容大家会在前边讲到。

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

当service
worker接管了页面之后,它或然有二种境况:要么被终止以节省里部存款和储蓄器,要么会处理fetch和message事件,那五个事件分别发生于三个网络请求出现仍然页面上发送了一个音讯。

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

图片 1

相称情形

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

image

当前浏览器PC辅助情形如图

境内第3浏览器扶助情状

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,可是1旦上线,就须要你的server支持HTTPS。

您能够透过service
worker勒迫连接,伪造和过滤响应,十分逆天。即使你可以约束本身不干坏事,也会有人想干坏事。所感觉了防御外人使坏,你只幸好HTTPS的网页上登记service
workers,那样大家才方可防备加载service
worker的时候不被歹徒篡改。(因为service
worker权限十分的大,所以要防御它自个儿被歹徒篡改利用——译者注)

Github
Pages
正好是HTTPS的,所以它是二个一石二鸟的自然实验田。

比方你想要让你的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 起先进入下多个生命周期状态 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-1511157771617)]

怎么样注册和安装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() 方法接收二个 promise 对象, 就算那么些 promise
对象 rejectedservice Worker 安装败北,状态改换为
Redundant。关于 cache 相关认证看下文。

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个缓存
  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事件。

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

那是一个提示用户更新的好机会,大概能够静默更新。

何以缓存和再次回到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。

如若大家有2个命中的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. 丰盛2个callback到fetch请求的 .then 方法中
  2. 要是我们获取了叁个response,大家开始展览如下的自笔者批评:
    1. 保险response是实惠的
    2. 检查response的处境是不是是200
    3. 保障response的花色是basic,那代表请求笔者是同源的,非同源(即跨域)的伸手也无法被缓存。
  3. 若是大家因此了自笔者批评,clone以此请求。这么做的原因是只要response是七个Stream,那么它的body只好被读取二次,所以大家得将它克隆出来,一份发给浏览器,一份发给缓存。

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状态。

哪些翻新3个Service Worker

您的service
worker总有要求更新的那壹天。当那一天来临的时候,你需求服从如下步骤来更新:

  1. 立异您的service worker的JavaScript文件
    1. 当用户浏览你的网址,浏览器尝试在后台下载service
      worker的剧本文件。只要服务器上的文书和地面文件有2个字节差异,它们就被剖断为要求更新。
  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的时候立时施行它,那么依旧在运维的旧版本的数目就坏了。

事先大家只利用了二个缓存,叫做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’
})

如此那般设计是有理由的,它比XH奥迪Q伍的在同源下私下认可发送凭据,但跨域时放弃凭据的条条框框要来得好。fetch的一言一动更像别的的CORubiconS请求,例如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

示例

fetch 基于stream 的 ,因此 response & request
1旦被消费则无从苏醒,所以这里在缓存的时候要求动用 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-COLacrosseS暗许不帮助

私下认可境况下,从第2方ULANDL跨域获得2个财富将会败北,除非对方扶助了CO福睿斯S。你能够增加三个non-CO奥德赛S选项到Request去防止退步。代价是那样做会回来2个“不透明”的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步骤缓存1个图形,你有以下两种选取:

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

正如好的方案是2或三,因为一旦把装有的图纸都给下载下来存着有点浪费内部存储器。

假定你将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" />

假若我们在一个二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
事件中缓存文件进程中,当在这之中2个文本加载失败,则 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
生命周期里登记。(不然会失利,调节台可知到警告)

谷歌(Google) 开采工具助力 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地图