Service Workers - JavaScript API 简介

做者: Felix Gerschau
译者:前端小智
来源:Felix Gerschau

最近开源了一个 Vue 组件,还不够完善,欢迎你们来一块儿完善它,也但愿你们能给个 star 支持一下,谢谢各位了。javascript

github 地址:https://github.com/qq44924588...css

service worker 是什么

Service Worker 是 Chrome 团队提出和力推的一个 WEB API,用于给 web 应用提供高级的可持续的后台处理能力。该 WEB API 标准起草于 2013 年,于 2014 年归入 W3C WEB 标准草案,当前还在草案阶段。html

Service Worker 最主要的特色是:在页面中注册并安装成功后,运行于浏览器后台,不受页面刷新的影响,能够监听和截拦做用域范围内全部页面的 HTTP 请求。前端

相似一个服务器与浏览器之间的中间人角色,若是网站中注册了service worker 那么它能够拦截当前网站全部的请求,进行判断(须要编写相应的判断程序),若是须要向服务器发起请求的就转给服务器,若是能够直接使用缓存的就直接返回缓存再也不转给服务器。从而大大提升浏览体验。vue

图片描述

Service Worker 能够启用之前原生应用程序专有的一组功能。 Service Worker 的初稿已于2014年发布,如今全部主流浏览器都支持它们。java

就像已经指出的定义同样,Service Worker 是网络代理。 这意味着它们能够控制页面中的全部网络请求,而且能够对其进行编程,使用缓存的进行响应。git

Service Worker 特色

  • 网站必须使用 HTTPS。除了使用本地开发环境调试时(如域名使用 localhost)
  • 运行于浏览器后台,能够控制打开的做用域范围下全部的页面请求
  • 单独的做用域范围,单独的运行环境和执行线程
  • 不能操做页面 DOM。但能够经过事件机制来处理

如何注册 Service Worker

注册 Service Worker 不须要太多代码,只须要一个用于Service Worker 代码的 JS 文件,通常取名为 service-worker.jsgithub

// 首先检查浏览器是否支持 Service Worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker
    .register('/sw/service-worker.js')
    .then(function(registration) {
      console.log(registration);
    })
    .catch(function(err) {
      console.log(err);
    });
}

其实关键代码只有一行:web

navigator.serviceWorker.register('/sw/service-worker.js')

注意:面试

Service Worker 的注册路径决定了其 scope 默认做用范围。示例中 service-worker.js 是在 /sw 路径下,这使得该 Service Worker 默认只会收到 /sw 路径下的 fetch事件。若是存放在网站的根路径下,则将会收到该网站的全部 fetcg事件。

若是但愿改变它的做用域,可在第二个参数设置 scope范围。示例中将其改成了根目录,即对整个站点生效。

另外应意识到这一点:Service Worker 没有页面做用域的概念,做用域范围内的全部页面请求都会被当前激活的 Service Worker 所监控。

Service Worker 能够启用哪些功能?

在本节中,我将进一步详细介绍Service Worker的功能,包括一些小代码示例。

服务工做者启用如下功能,这些功能也是 PWA的核心:

  • 离线功能
  • 按期后台同步
  • 推送通知

离线功能

Service Worke 经过缓存资源和拦截网络请求来提供离线功能,这些请求能够与先前缓存的资源一块儿使用,而不是从新请求服务器。

咱们能够从中得出两个步骤:

  • 预缓存
  • 从缓存中处理请求

这两个步骤都利用了Cache API,它由 Web Workers 和浏览器使用,而且为咱们提供了用于网络请求的存储机制。

对 Web 和服务工做人员上下文的 localStorage 访问被阻止,以防止并发性问题。做为一种替代方案,IndexedDB 能够用于存储大量数据。

预缓存

预缓存是一个术语,描述了在 Service Worker 处于激活状态以前下载和缓存文件。 它是在 Service Worker 生命周期的“install ”步骤中完成的。 一旦 Service Worker 处于激活状态,它将准备为缓存中的文件提供服务。

一般,咱们要缓存 Application Shell,这是运行网站所需的最少代码量。 若是开发了本机应用程序,那么这就是您将上传到应用程序商店的代码包。 这包括全部必需的基本JavaScript,HTML和图片。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(currentCache.offline).then(function(cache) {
      return cache.addAll([
        '/static/images/offline.svg',
        '/static/html/offline.html',
      ]);
    });
  );
});

从缓存中处理请求

在此阶段,咱们已经将全部应用程序代码存储在缓存中,而且Service Worker 已处于激活即运行于浏览器后台。

如今惟一缺乏的是监听 fetch 事件并从缓存中返回结果。能够经过 fetch 事件能够拦截到当前做用域范围内的 http/https 请求,而且给出本身的响应。结合 Fetch API ,能够简单方便地处理请求响应,实现对网络请求的控制。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

在本例中,咱们尽量使用缓存的内容进行响应。做为回退,咱们发出一个网络请求。

这里实现了一个缓存优先降级处理的策略逻辑:监控全部 http 请求,当请求资源已经在缓存里了,直接返回缓存里的内容;不然使用 fetch API 继续请求,若是是 图片或 cssjs 资源,请求成功后将他们加入缓存中;若是是离线状态或请求出错,则降级返回预缓存的离线内容。

按期后台同步

正如在引言中已经提到的那样,Service Worker 与其余服务工做者在一个单独的线程上运行,因此即便关闭页面,它们也能够执行其代码。 此功能对于执行后台同步和提供推送通知很重要。

后台同步

用户离开页面后,后台同步一般用于同步数据。

例如,在手机上编辑文档后,咱们写完会点击“保存”并离开页面。 若是在编辑文档期间链接断开,咱们必须等待链接恢复才能保存文档。

后台同步的目的是解决这个问题,一旦链接从新创建,自动发送数据。

来看一个示例:

app.js

navigator.serviceWorker.ready.then((registration) => {
  return registration.sync.register('sync-save-document');
});

service-worker.js

self.addEventListener('sync', (event) => {
  if (event.tag === 'sync-save-document') {
    event.waitUntil(saveDocument());
  }
});

saveDocument是一个返回 Promise,若是被拒绝(例如因为网络问题),同步将自动重试。

要注意的一件事是,同步标记必须是惟一的。 例如,若是我要安排5个“message”类型的后台同步,则只有最后一个会经过。 所以,在这种状况下,每一个标签都应具备惟一的标识符。

按期后台同步

按期后台同步解决与正常后台同步不一样的问题。 该API可用于在后台更新数据,而没必要等待用户。

这对不少应用程序都颇有用。有了这项技术,用户能够在没有互联网链接的状况下阅读最新的新闻文章。

为了防止滥用这一功能,同步的频率取决于浏览器为每一个网站设置的站点参与度分数。若是你常常打开一个网页应用,这个频率最多能够达到12个小时。

要实现此目的一个要求是,该网站已做为移动设备上的 PWA 安装并添加到主屏幕。

推送通知

Service Worker另外一个相似本机的特性是推送通知。咱们一般经过手机短信或社交媒体通知的形式知道它们,但它们也能够在台式电脑上使用。

Safari以外,全部主流浏览器都支持它们,而Safari对桌面应用程序有本身的实现。

要使用推送通知,须要设置一台服务器,该服务器会将通知推送给全部客户端。 因为Service Worker在后台在另外一个线程上运行,所以即便页面当前未打开,用户也能够看到推送通知。

推送的实现有两步:

不一样浏览器须要用不一样的推送消息服务器。以 Chrome 上使用 Google Cloud Messaging<GCM> 做为推送服务为例,第一步是注册 applicationServerKey(经过 GCM 注册获取),并在页面上进行订阅或发起订阅。每个会话会有一个独立的端点(endpoint),订阅对象的属性(PushSubscription.endpoint) 即为端点值。将端点发送给服务器后,服务器用这一值来发送消息给会话的激活的 Service Worker (经过 GCM 与浏览器客户端沟通)。

浏览器支持状况

clipboard.png

除了 Safari 和 IE/Edge,大部分现代浏览器都已经获得了支持。

总结

但愿经过本文介绍基本概念和特性,可让你更好地理解Service Worker


代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug

原文:https://felixgerschau.com/ser...

交流

文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。

相关文章
相关标签/搜索