菜单

Service Worker 从入门到进阶

2019年4月8日 - jQuery

Service Worker入门

2015/03/26 · JavaScript
· Service Worker

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

原生App拥有Web应用普通所不负有的富离线体验,定时的默不做声更新,音信通告推送等作用。而新的Serviceworkers标准让在Web App上全体这么些职能成为可能。

生命周期

image

Service Workermain.js
举行挂号,第1遍注册前会实行分析,判断加载的文书是不是在域名下,协议是还是不是为
HTTPS 的,通过那两点则成功注册。
service Worker 开首进入下3个生命周期状态 installinstall
达成后会触发 service Workerinstall 事件。 如果 install
成功则接下去是 activate动静, 然后那么些 service worker
才能接管页面。当事件 active 事件执行到位现在,此时 service Worker
有二种状态,1种是 active,一种是 terminatedactive
是为着工作,terminated则为了节本省部存款和储蓄器。当新的 service Worker 处于
install/waitting 阶段,当前 service Worker 处于
terminated,就会时有发生交接替换。恐怕能够经过调用 self.skipWaiting()
方法跳过等待。
被轮换掉的原本的 service WorkerRedundant 阶段,在 install 或者
activating 中断的也会进去 Redundant 阶段。所以3个 Service Worker
脚本的生命周期有那般某个等级(从左往右):

[图表上传退步…(image-af三cfa-1511157771617)]

fetch()的暗许参数

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

JavaScript

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

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

那样设计是有理由的,它比XHSportage的在同源下暗许发送凭据,但跨域时废弃凭据的条条框框要来得好。fetch的表现更像其余的COLacrosseS请求,例如<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

Redundant

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

倘假使后一种景况,则该 worker 照旧控制这么些页面。

值得注意的是早已 installservice worker
页面关闭后再打开不会触发 install 事件,然而会再一次登记。愈多参考文章
研究 Service Worker
「生命周期」

fetch()近日仅协助Service Workers

fetch立即协理在页面上行使了,然则当前的Chrome达成,它还只支持service
worker。cache
API也就要在页面上被援救,可是近年来截至,cache也还不得不在service
worker中用。

注意事项

参考

MDN
Service Worker
lifecycle

service worker
note

update service
worker

chrom service worker
sample

PWA 入门: 通晓和创制 Service Worker
脚本

PWA
在饿了么的实践经验

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

噩运,重定向在fetch()中不会被触发,那是当前版本的bug;

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() 方法接收3个 promise 对象, 假若那一个 promise
对象 rejectedservice Worker 安装失利,状态变更为
Redundant。关于 cache 相关表达看下文。

怎么创新三个Service Worker

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

  1. 革新您的service worker的JavaScript文件
    1. 当用户浏览你的网址,浏览器尝试在后台下载service
      worker的台本文件。只要服务器上的文本和本土文件有1个字节不一致,它们就被判定为急需创新。
  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 阶段的 service Worker 能够阻挡页面发出的
fetch,也得以发生fetch伸手,能够将呼吁和响应缓存在
cache里,也能够将 responsecache 中取出。

得到扶持

要是您遇见麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于大家立即跟进和尽只怕帮忙您消除难点。

赞 2 收藏
评论

图片 1

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

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得到2个promise并利用它来赢得安装开支的年月以及是还是不是安装成功。

假使具有的文本都被缓存成功了,那么service
worker就设置成功了。假若其余多少个文件下载退步,那么安装步骤就会失利。那几个措施允许你依靠于您本身钦点的具备财富,不过那意味你必要尤其严苛地控制哪些文件供给在设置步骤中被缓存。内定了太多的文书的话,就会扩大设置失利率。

地方只是三个简练的例证,你能够在install事件中履行此外操作依旧甚至忽视install事件。

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 控制全部

怎样注册和设置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中。

你会意识那一个成成效够很方便地在2个仿照窗口中测试你的service
worker,这样你能够关闭和重新打开它,而不会潜移默化到您的新窗口。任何制造在模仿窗口中的注册服务和缓存在窗口被关门时都将未有。

领会前的刺探

webWorker
fetch
cache
promise

Service Worker 是什么?

三个 service worker
是一段运营在浏览器后台进度里的台本,它独立于当下页面,提供了那么些不需求与web页面交互的功能在网页背后悄悄执行的力量。在今后,基于它可以实现消息推送,静默更新以及地理围栏等劳动,可是当前它首先要全数的效率是阻碍和拍卖互联网请求,包蕴可编制程序的响应缓存管理。

何以说那些API是2个不胜棒的API呢?因为它使得开发者能够支撑越来越好的离线体验,它赋予开发者完全控制离线数据的力量。

在service worker建议以前,别的3个提供开发者离线体验的API叫做App
Cache。然则App
Cache某些局限性,例如它能够很不难地化解单页应用的题材,但是在多页应用上会很麻烦,而Serviceworkers的产出正是为了缓解App Cache的痛点。

上边详细说一下service worker有何样需求留意的地点:

image

拍卖边界和填坑

那壹节内容比较新,有为数不少待定细节。希望那一节非常的慢就不必要讲了(因为标准会处理那几个题材——译者注),可是以后,那一个情节还是应当被提一下。

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

更加多内容

那里有部分有关的文书档案能够参照:https://jakearchibald.github.io/isserviceworkerready/resources.html

处理请求中离线情形

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

使用Service Worker

近年来大家有了polyfill,并且解决了HTTPS,让大家看看到底怎么用service
worker。

越发简的介

二〇一八年上马火遍南北的 PWA 技术诞生景况有负重望,主要来源 safrai
对于这一技术补助不甚美好,不扶助 mainfest 文件也不协理
service Worker

service worker 是贰个特殊的 web Worker,因而她与页面通讯和 worker
是一律的,同样不能够访问 DOM。特殊在于他是由事件驱动的有所生命周期的
worker,并且能够阻止处理页面包车型地铁互联网请求(fetch),可以访问 cache
IndexDB

换言之 service Worker
能够让开发者自个儿控制管理缓存的内容以及版本,为离线弱网环境下的 web
的运行提供了可能,让 web 在经验上越来越接近 native。

改变URL Hash的Bug

在M40版本中设有二个bug,它会让页面在变更hash的时候造成service
worker结束工作。

您可以在此间找到更加多相关的音信: https://code.google.com/p/chromium/issues/detail?id=433708

非常情状

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获得3个TLS证书。不相同的server安装方法分化,阅读扶助文书档案并经过Mozilla’s
SSL config
generator
打听最棒实践。

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

那是1个提示用户更新的好机遇,或许能够静默更新。

Service Worker的生命周期

Service worker拥有2个全然独立于Web页面包车型地铁生命周期。

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

在设置进度中,浏览器会加载并缓存一些静态能源。如若持有的公文被缓存成功,service
worker就安装成功了。假诺有别的文件加载或缓存失利,那么安装进度就会破产,service
worker就无法被激活(也即没能安装成功)。借使发生这么的题目,别担心,它会在下次再品尝安装。

当安装完成后,service
worker的下一步是激活,在这1品级,你还是能够升官一个service
worker的版本,具体内容我们会在后头讲到。

在激活之后,service
worker将接管全部在融洽管辖域范围内的页面,可是假诺二个页面是刚刚注册了service
worker,那么它那三回不会被接管,到下1遍加载页面包车型地铁时候,service
worker才会生效。

当service
worker接管了页面之后,它或然有二种景况:要么被截至以节省外部存款和储蓄器,要么会处理fetch和message事件,那四个事件分别发生于3个网络请求出现照旧页面上发送了2个新闻。

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

图片 3

拔尖实践

哪些缓存和再次来到Request

您曾经设置了service worker,你未来得以回去您缓存的伸手了。

当service
worker被安装成功还要用户浏览了另3个页面也许刷新了脚下的页面,service
worker将启幕接到到fetch事件。上面是2个事例:

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里,大家传入了1个由caches.match发生的promise.caches.match
查找request中被service worker缓存命中的response。

假如大家有1个命中的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次,所以我们得将它克隆出来,一份发给浏览器,1份发给缓存。

引进开关机制

开关是在饿了么实践经验里提议降级方案,通过向后端请求二个是还是不是降级的接口,假设降级则废除掉已经注册的service Worker。那里要留意不要缓存那个开关请求。为了方便难题排查,可以设置三个debug 格局(在 url 添加某个字符)。

拍卖响应式图片

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

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

  1. 设置具有的<picture>元素或者将被请求的srcset属性。
  2. 安装单一的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" />

要是大家在2个二x的来得情势下,浏览器会下载image-二x.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;" />

图片 4

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

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

假定设置战败了,未有很优雅的措施获取通报

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

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

缓存使用政策

从而可以依据使用的气象,使用缓存的 response
给到页面收缩请求及时响应,亦只怕将呼吁再次回到的结果更新到缓存,在运用离线时重返给页面。那便是以下的多种策略。

  1. 网络优先: 从网络获得, 退步只怕逾期再尝试从缓存读取
  2. 缓存优先: 从缓存获取,
    缓存插叙不到再品尝从网络抓取,在上文中的代码块就是该种策略的贯彻。
  3. 最快: 同时询问缓存和网络, 再次回到开端得到的
  4. 仅限网络: 仅从网络获取
  5. 仅限缓存: 仅从缓存获取

Non-COHavalS默许不支持

私下认可境况下,从第三方U君越L跨域获得一个能源将会失利,除非对方帮助了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 基于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;
          }
        );
      })
    );
});

破绽百出监察和控制

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 脚本])

相关文章

发表评论

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

网站地图xml地图