菜单

Service Worker入门

2019年4月3日 - CSS/CSS3

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有哪些供给留意的地点:

特别简的介

二零一八年开班火遍南北的 PWA 技术诞生情形有负重望,首要来自 safrai
对于这一技术援救不甚美好,不帮衬 mainfest 文件也不帮衬
service Worker

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

换言之 service Worker
能够让开发者自个儿决定管理缓存的内容以及版本,为离线弱网环境下的 web
的周转提供了说不定,让 web 在感受上更为靠近 native。

Service Worker的生命周期

Service worker拥有二个通通独立于Web页面的生命周期。

要让多少个service
worker在你的网址上生效,你要求先在您的网页中注册它。注册八个service
worker之后,浏览器会在后台默默运转叁个service worker的安装进程。

在安装进度中,浏览器会加载并缓存1些静态能源。如若全体的文书被缓存成功,service
worker就安装成功了。尽管有另伯公文加载或缓存失利,那么安装进程就会败北,service
worker就不可能被激活(也即没能安装成功)。如果发生如此的难点,别担心,它会在下次再品尝安装。

当安装完结后,service
worker的下一步是激活,在那1阶段,你还是可以升高七个service
worker的本子,具体内容我们会在背后讲到。

在激活之后,service
worker将接管全数在温馨管辖域范围内的页面,不过一旦三个页面是刚刚注册了service
worker,那么它此番不会被接管,到下2遍加载页面包车型客车时候,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 开始进入下一个生命周期状态 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陆一7)]

怎么样注册和设置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. 缓存大家的文书
  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就设置成功了。如若其余三个文本下载战败,那么安装步骤就会破产。那么些方法允许你依靠于你协调钦定的富有能源,不过那意味你必要越发严厉地决定怎么样文件要求在装置步骤中被缓存。钦赐了太多的文件的话,就会增多设置退步率。

上边只是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
    }
})

那是三个唤起用户更新的好机遇,或然能够静默更新。

什么样缓存和再次回到Request

你早已安装了service worker,你未来得以回到您缓存的央求了。

当service
worker被设置成功还要用户浏览了另2个页面或许刷新了近日的页面,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,大家重临被缓存的值,否则大家回来一个实时从网络请求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只可以被读取一回,所以大家得将它克隆出来,一份发给浏览器,壹份发给缓存。

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. 履新后的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
});

处理边界和填坑

那1节内容比较新,有不可胜计待定细节。希望这一节十分的快就不供给讲了(因为标准会处理那些题材——译者注),不过今后,这几个内容依然应该被提一下。

Redundant

service Workerinstall active经过中处错误只怕,被新的
service Worker 替换状态会化为 Redundant

假若是后壹种情形,则该 worker 还是控制那几个页面。

值得注意的是现已 installservice worker
页面关闭后再打开不会触发 install 事件,但是会重复登记。越多参考小说
琢磨 瑟维斯 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’
})

那般设计是有理由的,它比XHLacrosse的在同源下私下认可发送凭据,但跨域时吐弃凭据的平整要来得好。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-CORubiconS暗中同意不协理

暗中同意意况下,从第一方U卡宴L跨域获得三个财富将会破产,除非对方帮衬了CO安德拉S。你能够添加一个non-CO宝马X5S选项到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 团队的开发者
Jeff 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. 设置单壹的low-res版本图片
  3. 安装单1的high-res版本图片

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

设若你将low-res版本在install的时候缓存了,然后在页面加载的时候你想要尝试从网络上下载high-res的本子,不过就算high-res版本下载退步以来,就依旧用low-res版本。这么些想法很好也值得去做,不过有1个难题:

比方大家有下边三种图片:

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

若是大家在1个二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版本中留存三个bug,它会让页面在变更hash的时候造成service
worker甘休工作。

你能够在此间找到愈多相关的音信: https://code.google.com/p/chromium/issues/detail?id=433708

处理请求中离线情状

service Worker 发送请求时,捕获分外,并回到页面1个 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地图