来自 业界快讯 2019-11-28 05:03 的文章
当前位置: 118kj开奖现场 > 业界快讯 > 正文

Service Worker入门

Service Worker入门

2015/03/26 · JavaScript · Service Worker

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

  • 十年踪迹]()   

原生App具有Web应用普通所不持有的富离线体验,依期的守口如瓶更新,新闻文告推送等功效。而新的Serviceworkers规范让在Web App上具备这个功用成为可能。

Service Worker 是什么?

贰个 service worker 是生龙活虎段运转在浏览器后台进度里的本子,它独立于如今页面,提供了这几个无需与web页面交互作用的成效在网页背后悄悄实行的力量。在今日,基于它可以完成音讯推送,静默更新乃至地理围栏等劳动,可是方今它首先要负有的职能是挡住和管理互联网央浼,包罗可编程的响应缓存管理。

缘何说这么些API是二个分外棒的API呢?因为它使得开荒者可以支撑特别好的离线体验,它授予开荒者完全调整离线数据的技巧。

在service worker建议以前,其它七个提供开拓者离线体验的API叫做App Cache。然则App Cache有个别局限性,举个例子它能够相当轻便地减轻单页应用的主题材料,不过在多页应用上会很麻烦,而Serviceworkers的产出正是为了消除App Cache的痛点。

下边详细说一下service worker有哪些必要小心的地点:

  • 它是JavaScript Worker,所以它无法平素操作DOM。可是service worker可以经过postMessage与页面之间通讯,把信息文告给页面,假若须求的话,让页面自身去操作DOM。
  • Serviceworker是一个可编制程序的互连网代理,允许开荒者调节页面上拍卖的互联网央浼。
  • 在不被选择的时候,它会和煦终止,而当它再度被用到的时候,会被重复激活,所以您不可能依据于service worker的onfecth和onmessage的管理函数中的全局状态。借使您想要保存一些持久化的音讯,你能够在service worker里使用IndexedDB API。
  • Serviceworker多量使用promise,所以即便你不掌握什么是promise,那您须求先读书这篇文章。

Service Worker的生命周期

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

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

在安装进度中,浏览器会加载并缓存一些静态能源。假设全体的文书被缓存成功,service worker就安装成功了。尽管有其余文件加载或缓存退步,那么安装进程就能倒闭,service worker就无法被激活(也即未能安装成功卡塔 尔(阿拉伯语:قطر‎。若是发生这样的主题素材,别顾忌,它会在后一次再品尝安装。

当安装到位后,service worker的下一步是激活,在此风流浪漫等第,你还是能够晋级一个service worker的本子,具体内容大家会在背后讲到。

在激活之后,service worker将接管全体在和睦管辖域范围内的页面,不过只要叁个页面是刚刚注册了service worker,那么它那三回不会被接管,到下一回加载页面包车型大巴时候,service worker才会生效。

当service worker接管了页面之后,它或者有二种状态:要么被结束以节本省部存款和储蓄器,要么会处理fetch和message事件,那八个事件分别爆发于贰个网络央求出现依旧页面上发送了贰个音讯。

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

118kj开奖现场 1

118kj开奖现场,在我们初叶写码此前

从这个品类地址拿到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打探最棒实行。

使用Service Worker

前些天我们有了polyfill,而且解决了HTTPS,让我们看看见底怎么用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是否对你的网站启用了。

118kj开奖现场 2

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

你会意识那个意义能够很方便地在二个仿照窗口中测量试验你的service worker,那样你能够关闭和重新张开它,而不会影响到你的新窗口。任何创设在模拟窗口中的注册服务和缓存在窗口被关闭时都将无影无踪。

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卡塔 尔(英语:State of Qatar)实现的。event.waitUntil得到二个promise并利用它来赢得安装开支的光阴以至是或不是安装成功。

例如具备的文本都被缓存成功了,那么service worker就设置成功了。借使别的二个文书下载退步,那么安装步骤就能够倒闭。那些措施允许你依赖于你协和钦赐的具备能源,不过那表示你须要极其严厉地操纵怎么样文件要求在设置步骤中被缓存。钦赐了太多的文书的话,就能追加设置退步率。

地点只是叁个轻便易行的事例,你可以在install事件中推行其余操作依然以致忽略install事件。

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

若果大家有三个命中的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只好被读取一次,所以咱们得将它克隆出来,意气风发份发给浏览器,生机勃勃份发给缓存。

什么改革三个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);
          }
        })
      );
    })
  );
});

拍卖边界和填坑

那生龙活虎节内容比较新,有数不胜数待定细节。希望那少年老成节相当慢就没有必要讲了(因为规范会管理这几个难题——译者注卡塔尔国,不过今后,这么些内容依然应该被提一下。

要是设置战败了,未有超高贵的主意赢得通报

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

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

fetch()近年来仅补助Service Workers

fetch立刻扶植在页面上利用了,不过当前的Chrome完结,它还只援救service worker。cache API也即就要页面上被援救,然而如今截至,cache也还一定要在service worker中用。

fetch()的暗中同意参数

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

JavaScript

fetch(url, { credentials: 'include' })

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

那样设计是有理由的,它比XHENVISION的在同源下暗中同意发送凭据,但跨域时放弃凭据的规规矩矩要来得好。fetch的展现更像别的的CO哈弗S需要,举个例子<img crossorigin>,它默认不发送cookies,除非你指定了<img crossorigin="use-credentials">.。

Non-CO路虎极光S暗许不协助

默许处境下,从第三方USportageL跨域获得贰个能源将会失利,除非对方帮助了COOdysseyS。你能够加上三个non-CO宝马7系S选项到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;

拍卖响应式图片

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

在service worker中,你想要在install步骤缓存一个图纸,你有以下三种采纳:

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

比较好的方案是2或3,因为假若把具备的图样都给下载下来存着有一点浪费内部存款和储蓄器。

比如你将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" />

万风姿罗曼蒂克大家在叁个2x的来得形式下,浏览器会下载image-2x.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;" />

118kj开奖现场 3

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

改变URL Hash的Bug

在M40版本中留存多个bug,它会让页面在改造hash的时候产生service worker甘休职业。

您能够在此边找到越多相关的新闻: 

越多内容

那边有局地连锁的文书档案能够参照:

拿到扶持

设若你遇见麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于我们立马跟进和尽恐怕辅助您消除难题。

赞 2 收藏 评论

118kj开奖现场 4

本文由118kj开奖现场发布于业界快讯,转载请注明出处:Service Worker入门

关键词: