首页

当前位置:永利皇宫463登录 > 首页 > 从入门到升级

从入门到升级

来源:http://www.makebuLuo.com 作者:永利皇宫463登录 时间:2019-11-15 01:33

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有如何须求注意的地方:

  • 它是JavaScript Worker,所以它不能够一向操作DOM。但是service worker能够通过postMessage与页面之间通讯,把新闻布告给页面,假使必要的话,让页面自身去操作DOM。
  • Serviceworker是四个可编制程序的互连网代理,允许开辟者调控页面上拍卖的互联网央浼。
  • 在不被应用的时候,它会融洽终止,而当它再度被用到的时候,会被另行激活,所以您无法依赖于service worker的onfecth和onmessage的管理函数中的全局状态。固然你想要保存一些长久化的新闻,你可以在service worker里使用IndexedDB API。
  • Serviceworker多量使用promise,所以如果您不打听怎样是promise,那你必要先读书这篇文章。

特别简的介

二〇一八年底步火遍南北的 PWA 技能诞生意况有负重望,首要根源 safrai 对于这一本事援助不甚美好,不扶植 mainfest 文件也不扶持 service Worker

service worker 是八个不相同平日的 web Worker,因此他与页面通讯和 worker 是如出黄金年代辙的,同样不能访谈 DOM。特殊在于他是由事件驱动的全数生命周期的 worker,並且可以阻碍管理页面包车型大巴互联网伏乞(fetch),能够访问 cacheIndexDB

换言之 service Worker 能够让开拓者本身主宰处理缓存的剧情以致版本,为离线弱网情况下的 web 的周转提供了说不好,让 web 在体会上尤为临近 native。

初期思忖

常常来讲的底蕴知识:

  • Angular service workers介绍.

从5angular.0.0始发,在大肆cli项目中,你能够相当轻巧的开启Angular service worker。那文书档案是介绍怎么去在新的或旧的种类中启用Angular service worker。会透过一个简约的例证是显示service worker的一举一动与主干缓存。

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初次安装的生命周期:

图片 1

相称情况

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

image

当下浏览器PC帮忙情形如图

本国重大浏览器帮衬情状

android 设备在 4.4 版本采取 Chromium 作为功底,Chromium 在 40 对于 service worker 援助。国内浏览器蕴含微信浏览器在内基本已经支撑 service Worker 那为升高体验提供了大概。service workerHTTP2 越发配哦,在几眼前基于它能够兑现音讯推送,静默更新以致地理围栏等劳动。

在新类型中增添service worker

若果你要生成二个新的cli项目,你可以接收cli去配置Angular service worker:

ng new my-project --service-worker

--service-worker指令会去做有所的布署并累计要求依附的包。想打听越多,可查阅上边包车型地铁关于什么在旧项目增添service worker的证实

在大家开头写码早先

从这个花色地址拿到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权限非常的大,所以要严防它本人被混蛋窜改利用——译者注卡塔 尔(英语:State of Qatar)

Github Pages正好是HTTPS的,所以它是二个美观的先性格实验田。

假使您想要让您的server支持HTTPS,你必要为你的server获得二个TLS证书。差异的server安装方法区别,阅读帮忙文书档案并透过Mozilla’s SSL config generator刺探最棒实行。

精通前的刺探

webWorker
fetch
cache
promise

在旧项目中增添service worker

增多步骤:

  1. 增添service worker的包信任。
  2. 在cli配置中启用service worker。
  3. 导入和挂号service worker。
  4. 新建配置文件,定义缓存的一言一动和其余设定。
  5. 编写翻译项目。

使用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-af3cfa-1511157771617)]

步骤1:增多service worker的包信任。使用yarn包管理工科具:

yarn add @angular/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中。

你会发觉那么些效果能够很方便地在贰个模拟窗口中测量试验你的service worker,那样您能够关闭和另行张开它,而不会影响到你的新窗口。任何创立在模拟窗口中的注册服务和缓存在窗口被关闭时都将熄灭。

Install

install 存在中间态 installing 那几个处境在 main.jsregistration注册对象中可以访问到。

/* 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 相关认证看下文。

步骤2:在cli配置中启用service worker:

要开启Angular service worker,cli必得在编译时生成Angular service worker的安顿。要在旧项目中布告cli去做这一步,必需把.angular-cli.json文件里的 serviceWorker的值改成true

ng set apps.0.serviceWorker=true

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就安装成功了。如若别的一个文本下载退步,那么安装步骤就能够破产。那几个艺术允许你依据于你协调钦点的兼具财富,不过那意味你须要极度严峻地决定怎样文件须要在装置步骤中被缓存。钦赐了太多的文本的话,就能够追加设置失利率。

上面只是四个粗略的事例,你能够在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:导入和挂号service worker:

src/app/app.module.ts中:

import  {  [ServiceWorkerModule](https://angular.io/api/service-worker/ServiceWorkerModule)  }  from  '@angular/service-worker';  
import  { environment }  from  '../environments/environment';

@NgModule({ 
declarations:  [  AppComponent  ], 
imports:  [  
   BrowserModule,  
   ServiceWorkerModule.register('/ngsw-worker.js',  {enabled: environment.production})  
   ], 
   providers:  [ ],
   bootstrap:  [AppComponent]
 })  
export  class  AppModule  {  }

ngsw-worker.js文件是cli编译生成的service worker脚本,最终能在dist/里找到。

什么缓存和重回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只好被读取一回,所以我们得将它克隆出来,黄金时代份发给浏览器,生机勃勃份发给缓存。

Activating

  • 当页面未有正在周转的 service Worker时;
  • service Worker本子中调用了 self.skipWaiting 方法;
  • 客户切换页面使本来的 service Worker 释放;
  • 特定失效已过,释放由此原有的 service Worker 被释放

则状态成为 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 方法。当所收到的 promisereject 那么 serviceWorker 进入 Redundant状态。

步骤4: 新建配置文件, ngsw-config.json

angular cli须求名叫ngsw-config.json的service worker配置文件。那文件定义了如何去缓存文件与数据财富。

您能够利用cli产生的通用配置版本

也许,将以下内容保存为src/ ngsw-config.json:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html"
      ],
      "versionedFiles": [
        "/*.bundle.css",
        "/*.bundle.js",
        "/*.chunk.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }]
}

什么样创新二个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
});

步骤 5: 编写翻译项目

ng build --prod

产生的类型就是启用了Angular service worker了.

管理边界和填坑

那大器晚成节内容相比新,有为数不菲待定细节。希望这豆蔻梢头节一点也不慢就没有必要讲了(因为标准会管理那个难题——译者注卡塔 尔(英语:State of Qatar),不过今后,那几个剧情还是应当被提一下。

Redundant

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

比如是后大器晚成种情景,则该 worker 依旧调节这几个页面。

值得注意的是早已 installservice worker 页面关闭后再展开不会触发 install 事件,但是会重新挂号。更加的多参谋小说 索求 Service Worker 「生命周期」

Service worker 的体现表达

此模块通过二个演示来呈现表达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 中取出。

选用http-server创设服务器

因为ng serve 不会运行service worker,你一定要选用另八个http服务器去本地质衡量试你的类型。你能够行使其余的HTTP服务器。下边例子是利用http-server,能够经过npm安装。为了降低冲突的或者性,将要贰个专项使用的端口测验。
要使用http-server拉开服务,要运动到打包文件的文本夹内然后开发银行web服务:

cd dist
http-server -p 8080

fetch()近些日子仅协助Service Workers

fetch顿时扶助在页面上接纳了,但是当前的Chrome完成,它还只帮衬service worker。cache API也将在在页面上被扶助,可是最近结束,cache也还只可以在service worker中用。

缓存使用政策

就此得以依靠使用的现象,使用缓存的 response 给到页面缩短乞请及时响应,亦或然将诉求再次来到的结果更新到缓存,在选取离线时回来给页面。那就是以下的有余政策。

  1. 互连网优先: 从互连网得到, 退步大概逾期再品尝从缓存读取
  2. 缓存优先: 从缓存获取, 缓存插叙不到再品尝从网络抓取,在上文中的代码块正是该种计谋的兑现。
  3. 最快: 相同的时间询问缓存和网络, 再次回到最初获得的
  4. 只限互连网: 仅从网络拿到
  5. 只限缓存: 仅从缓存获取

初次加载

劳务运行中,你可以在浏览器访谈http://localhost:8080/。你的施用应该是平日运行。

提示:当测量试验Angular service workers,最棒是在浏览器中应用无痕或私有窗口,那能确定保证service worker不会从原先的预先留下的缓存中读取数据,产生意外的景况。

fetch()的暗许参数

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

JavaScript

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

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

如此设计是有理由的,它比XHEnclave的在同源下暗中同意发送凭据,但跨域时抛弃凭据的平整要来得好。fetch的一言一动更像任何的COCR-VS要求,举例<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;
          }
        );
      })
    );
});

仿照互联网难题

要效仿互联网难点,可幸免利用的互联网连接。在Chrome内:

  1. Select Tools > Developer Tools (开荒职职员和工人具).
  2. 进入Network分页.
  3. 勾选the Offline 项.

图片 3

Now the app has no access to network interaction.
现行反革命选取没有办法访问互联网了。

对此那几个并未有动用Angular service worker的行使,刷新页面会显示 "There is no Internet connection"的页面。

加多了Angular service worker的利用不相同样。刷新后,页面符合规律呈现。
借令你查看Network 分页的音讯,你就会验证service worker是在职业。

图片 4

Non-COEvoqueS默许不援助

私下认可景况下,从第三方UTiguanL跨域得到二个财富将会停业,除非对方扶助了CO揽胜S。你能够增添三个non-CO瑞虎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.');
});

精品施行

怎么被缓存

会意识全体用来渲染app的文件都被缓存了。给cli使用的通用ngsw-config.json正是概念了缓存这个特定的财富:

  • index.html.
  • favicon.ico.
  • 编写翻译的文件 (JS and CSS bundles).
  • assets文件夹里的具备文件.

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 调整全数

改革你的利用

当今您曾经见到service worker怎么着缓存你的行使,下一步是明白更新如何做事。

  1. 借令你在叁个无痕窗口中测量试验,展开另贰个分页。这会使事态和缓存不会再测量检验中消失。
  2. 关闭应用的分页,但不是浏览器。那也会倒闭了开垦者工具。
  3. 关闭http-server的服务。
  4. 下一步,校勘应用,查看service worker安装更新。
  5. 打开src/app/app.component.html并编辑
  6. 改正文件 Welcome to {{title}}! 为 Bienvenue à {{title}}!.
  7. 再一次编写翻译并运维服务
ng build --prod
cd dist
http-server -p 8080

拍卖响应式图片

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

图片 5

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

在浏览器中纠正您的采纳

前几天观察浏览器和service worker是如什么地方理更新了的选取

  1. 在同等浏览器再一次张开http://localhost:8080 。产生什么样?

    图片 6

哪里出错了?实际是没有的。Angular service
worker就在执行它的工作,展示它已安装的应用的版本。尽管有一个可用的更新。为了提高速度,service
worker会在完成展示已缓存的应用后才去检查更新。

设若你查看http-server的日记,你就足以见到service worker央求/ngsw.json。那是service worker在检查更新。

  1. 刷新页面.

图片 7

service worker在后台装置了翻新的app版本,下一次页面加载或重加载时,service worker就显得最新的本子。

改变URL Hash的Bug

在M40版本中设有三个bug,它会让页面在转移hash的时候变成service worker甘休专门的学业。

你可以在那间找到更加的多相关的音信: 

管理须求中离线情形

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

越多的有关 Angular service workers

您只怕对以下感兴趣

  • 与service workers的交互.

你们的称扬是自身的不过引力

越多内容

此间有生龙活虎对连锁的文书档案能够参见:

引进开关机制

按钮是在饿了么实施资历里建议降级方案,通过向后端需要叁个是或不是降级的接口,如若降级则撤除掉已经登记的service Worker。这里要注意不要缓存这些按钮央浼。为了有助于难题排查,能够设置七个debug 情势(在 url 增多有些字符卡塔尔。

取获救助

借使您遇见麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于大家马上跟进和尽只怕协理您消除难点。

赞 2 收藏 评论

图片 8

乖谬监察和控制

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 文件:

  • sw-precache用于转移页面所需静态资源列表,近日有 webpack 插件 sw-precache-webpack-plugin 能够相配
  • sw-toolbox 提供了动态缓存使用的通用战术, 这个动态的能源不合适用 sw-precache 预先缓存。同期它提供了风度翩翩套相通 Express.js 路由的语法, 用于编写攻略。它还提供了 LRU 替换战略与 TTL 失效机制,能够确定保障大家的应用不会超越浏览器的缓存分配的定额。

更多[参谋文章]([PWA 入门: 理解和开创 Service Worker 脚本])

注意事项

  • 功能域:出于安全原因, Service Worker 脚本的效能范围不能够超越脚本文件所在的路子。比方地址是 "/sw-test/sw.js" 的本子只可以调整 "/sw-test/" 下的页面。
  • 本土开拓条件足以选拔 http 协议, 上线必须选取https 协议。
  • Service Worker 中的 Javascript 代码必得是非梗塞的,所以你不该在 Service Worker 代码中是用 localStorage 以及 XMLHttpRequest
  • 在页面关闭后,浏览器能够世袭维持service worker运转,也得以关闭service worker,那决定于与浏览器本人的一举一动,所以不用在 serviceWorker.js 中定义全局变量,假诺想要保存一些漫长化的新闻,你可以在service worker里使用IndexedDB API。

参考

MDN
Service Worker lifecycle
service worker note
update service worker
chrom service worker sample
PWA 入门: 通晓和创建 Service Worker 脚本
PWA 在饿了么的实践经历

本文由永利皇宫463登录发布于首页,转载请注明出处:从入门到升级

关键词: