从入门到进阶

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是3个可编程的互连网代理,允许开发者控制页面上处理的网络请求。
  • 在不被选拔的时候,它会友善终止,而当它再一次被用到的时候,会被另行激活,所以您不可能依靠于service
    worker的onfecth和onmessage的处理函数中的全局状态。如若您想要保存一些持久化的新闻,你能够在service
    worker里使用从入门到进阶。IndexedDB API。
  • Serviceworker大批量使用promise,所以若是您不打听怎么样是promise,那你必要先读书这篇文章。

特别简的介

2018年初步火遍南北的 PWA 技术诞生情形有负重望,主要来源于 safrai
对于这一技术援救不甚美好,不帮助 mainfest 文件也不支持
service Worker

service worker 是3个卓殊的 web Worker,由此她与页面通讯和 worker
是同样的,同样无法访问 DOM。特殊在于他是由事件驱动的享有生命周期的
worker,并且能够阻挡处理页面包车型地铁网络请求(fetch),可以访问 cache
IndexDB

换言之 service Worker
可以让开发者本人支配管理缓存的始末以及版本,为离线弱网环境下的 web
的运转提供了也许,让 web 在体会上更是接近 native。

最初准备

正如的基础知识:

  • Angular service
    workers介绍.

从5angular.0.0始发,在任意cli项目中,你能够很简单的开启Angular service
worker。那文书档案是介绍怎么去在新的或旧的项目中启用Angular service
worker。会因而多少个大概的例证是展现service worker的行为与主旨缓存。

采纳前的安装:

Chrome中须要开启相关布署: 访问
chrome://flags 并拉开
experimental-web-platform-features; 重启浏览器
(注意:有个别特性在Chrome中一向不暗中同意开放扶助);此外,你需求通过 HTTPS
来访问你的页面 — 出于安全原因,Service Workers 须要要在必得在 HTTPS
下才能运作,localhost 也被浏览器认为是安全源。

Service Worker的生命周期

Service worker拥有三个一心独立于Web页面包车型大巴生命周期。

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

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

当安装完毕后,service
worker的下一步是激活,在这一等级,你还足以升级2个service
worker的版本,具体内容我们会在末端讲到。

在激活之后,service
worker将接管全部在祥和管辖域范围内的页面,不过如若二个页面是刚刚注册了service
worker,那么它那二次不会被接管,到下3遍加载页面包车型地铁时候,service
worker才会生效。

当service
worker接管了页面之后,它也许有二种境况:要么被终止以节省外部存款和储蓄器,要么会处理fetch和message事件,那多个事件分别发出于2个互连网请求出现依然页面上发送了三个新闻。

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

图片 1

非凡意况

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

image

日前浏览器PC帮忙意况如图

境内重点浏览器补助情形

android 设备在 4.4 版本选择 Chromium 作为基石,Chromium 在 40
对于 service worker 接济。国内浏览器包蕴微信浏览器在内基本已经帮衬
service Worker 那为进步体验提供了也许。service workerHTTP2
特别配哦,在后天基于它能够兑现音信推送,静默更新以及地理围栏等劳动。

在新品类中添加service worker

若果您要生成1个新的cli项目,你能够利用cli去配置Angular service worker:

ng new my-project --service-worker

--service-worker命令会去做有所的配备并加上需求注重的包。想询问越多,可查看下边包车型大巴有关如何在旧项目添加service
worker的表明

简简单单的例证

那是把express和sw-test简单结合的3个小demo, 项目周转起来访问
http://localhost:3000/sw-test/index.html
,
然后停下此服务还能访问相应能源。Github

在大家先导写码以前

从这个连串地址拿到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打听最佳实践。

询问前的打听

webWorker
fetch
cache
promise

在旧项目中添加service worker

添加步骤:

  1. 添加service worker的包注重。
  2. 在cli配置中启用service worker。
  3. 导入和挂号service worker。
  4. 新建配置文件,定义缓存的作为和其余设定。
  5. 编写翻译项目。

有关代码

  • /public/sw-test/app.js
  1. 第三判断了浏览器是不是援救
  2. 调用 register 方法注册 service worker, 第③个参数是运营 service
    worker 的
    js 文件, 第3个 scope 参数是选填的,能够被用来钦点你想让 service
    worker 控制的内容的子目录。 在这几个例子,我们钦点了 ‘/sw-test/’,即
    http://localhost:3000/sw-test/
    下的呼吁会被抓走, 被钦定的能源会被缓存。
  3. register 方法再次回到五个 Promise , 进行科学错误处理。

  if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
    // registration worked
    console.log('Registration succeeded. Scope is ' + reg.scope);
  }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
  });
}
  • /public/sw-test/sw.js
    中央文件,监听安装事件, 打开缓存 v1 扩大内需缓存能源 request url
    list, 截取被控文件下请求, 借使不存在该缓存则开始展览缓存处理
  1. 监听了 install 事件, event.waitUntil 重要用在 Install, activate
    事件中,
    在劳动办事线程中,延长事件的寿命从而阻碍浏览器在事变中的异步操作完毕在此以前终止服务工作线程。
  2. Cache 接口提供缓存的
    Request,
    Response
    对象对的贮存机制,例如作为ServiceWorker生命周期的一有的。
    Cache 接口像 workers 一样, 是揭露在 window
    功能域下的。固然它被定义在 service worker 的专业中,
    但是它不必一定要同盟 service worker
    使用.Cache详细API
  3. event.respondWith
    方法意在包裹代码,那个代码为来源受控页面包车型大巴request生成自定义的response,查阅更加多。response.clone()
    成立了1个响应对象的克隆,那几个指标在享有地方都以千篇一律的,可是存款和储蓄在一个见仁见智的变量中。制止反复运用篡改了目标。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('v1').then(function(cache) {
      return cache.addAll([
        '/sw-test/',
        '/sw-test/index.html',
        '/sw-test/style.css',
        '/sw-test/app.js',
        '/sw-test/image-list.js',
        '/sw-test/star-wars-logo.jpg',
        '/sw-test/gallery/bountyHunters.jpg',
        '/sw-test/gallery/myLittleVader.jpg',
        '/sw-test/gallery/snowTroopers.jpg'
      ]);
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(caches.match(event.request).then(function(response) {
    // caches.match() always resolves
    // but in case of success response will have value
    if (response !== undefined) {
      return response;
    } else {
      return fetch(event.request).then(function (response) {
        // response may be used only once
        // we need to save clone to put one copy in cache
        // and serve second one
        let responseClone = response.clone();

        caches.open('v1').then(function (cache) {
          cache.put(event.request, responseClone);
        });
        return response;
      }).catch(function () {
        return caches.match('/sw-test/gallery/myLittleVader.jpg');
      });
    }
  }));
});

使用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

本子更新删除旧缓存

  1. 监听 activate 事件, 如当前版本 v2,删除与日前不匹配缓存数据。

this.addEventListener('activate', function(event) {
  var cacheWhitelist = ['v2'];

  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheWhitelist.indexOf(key) === -1) {
          return caches.delete(key);
        }
      }));
    })
  );
});

什么样注册和设置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() 方法接收1个 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

参照 MDN

Service Worker
详细文书档案

网站地图xml地图