写在前面

  • 作者:Flavio Copes
  • 原文地址:Service workers: the little heroes behind Progressive Web Apps
  • 说明:本人水平有限,在翻译过程中难免有理解翻译不准确的地方,为避免错误引导大家,希望能够指,向大家传递正确的观点和知识。

正文

Service workers是PWA应用的核心。它能够缓存资源以及推送消息,这正是使原生应用与众不同的最大的两个特性。
一个service worker就是你的页面和网络之间的一个可编程代理,它提供了拦截和缓存网络请求的能力。这种能力使得你可以为你的web应用创造一种离线体验
Service workers是一种特殊的web线程:与web页面相关联的一个JavaScript文件,该文件运行在一个worker上下文中,与主线程分开。这就带来了一种非阻塞的好处-能够使你的运算在不影响UI响应的情况下进行。
因为它是在一个独立线程上的,所以没有DOM访问。它也不能访问本地存储API和XHR API。它只能通过通道消息传递API与主线程通信。
Service workers最近与其它的几个web APIs合作:

  • Promises
  • Fetch API
  • Cache API

它们只能在HTTPS协议的页面上使用(除了本地请求,这些不需要安全连接。使得测试更加简单)。 #### 后台处理 Service workers独立于与之关联的应用程序运行,并且在不活动时可以接收消息。
例如,在以下这些情况下它也可以运行:

  • 当您的移动应用程序处于后台时,不活动
  • 当您的移动应用程序关闭,甚至不运行在后台
  • 当浏览器关闭时,如果应用程序在浏览器中运行

Service workers发挥重要作用的场景:

  • 它们可以作为缓存层来处理网络请求,以及在脱机时使用的缓存内容。
  • 它们可以推送消息。

一个Service worker只在需要时才运行,当不需要时就会停止。

支持离线

通常,web应用的离线体验是非常差的。没有网络时,移动web应用直接停止工作。另一方面,原生应用能够提供一个可工作版本或者一些非常好的信息。
这不是一个很好的消息,但是这是一个没有网络连接的Chrome网页的样子:

也许,唯一的好处就是你可以点击恐龙来玩免费的游戏-但你很快就会觉得无聊。 在最近的几年,HTML5 AppCache已经能够让web应用缓存资源以及离线工作了。但是它缺乏足够的灵活性和令人困惑的应用效果证明它并不能很好地解决这个问题(并且它已经被弃用了)。
Service workers是离线缓存的新标准。
哪种缓存是可能的?

在安装期间预缓存资源

在整个应用程序中能够重用的资源,比如图片、CSS、JS文件,能够在应用打开的第一时间就被安装。
这为App Shell架构提供了基础。

缓存网络请求

使用Fetch API,我们能够编辑来自服务的响应,确定服务器是否可访问,并从缓存中提供响应。

Service Worker的生命周期

一个Service Worker经过三步完成一个完整的功能:

  • 注册
  • 安装
  • 激活

注册

注册就是告诉浏览器这个Service Worker在什么地方以及在后台运行安装。
比如,在worker.js中注册一个Service Worker:

if ('serviceWorker' in navigator) { window.addEventListener('load', () => {   navigator.serviceWorker.register('/worker.js') .then((registration) => { console.log('Service Worker registration completed with scope: ', registration.scope) }, (err) => { console.log('Service Worker registration failed', err)})})
} else { console.log('Service Workers not supported')
}
复制代码

即使代码被调用多次或者已经被更新了,那么如果这个Service Worker是新的,而且之前没有被注册过,浏览器将只执行注册。

范围

register()函数也将接受一个范围参数,这个参数是个路径决定了应用程序的哪一部分可以由Service Worker控制。
它默认包含在包Service Worker文件的文件夹中的所有文件和子文件夹,所以,如果你把它放到根文件中,它将控制整个应用。在子文件中,它将只控制这个路径下的页面。
下面的示例通过/notifications/文件夹范围来注册worker。

navigator.serviceWorker.register('/worker.js', { scope: '/notifications/'
})
复制代码

这个/是非常重要的:在这种情况下,页面/notifications将不会触发Service Worker,然而如果这个范围是:

{ scope: '/notifications' }
复制代码

它就会奏效。
注意:Service Worker不能在一个文件中向外提升自己:如果它的文件放在/notifications下,它将不能控制/路径或者其它任何不在/notifications文件内的路径。 #### 安装 如果浏览器确定Service Worker已经过时或从未注册过,它将去安装它:

self.addEventListener('install', (event) => { //...
});
复制代码

这是一个很好的时机,可以让Service Worker通过初始化缓存来使用。然后使用缓存API缓存应用程序Shell和静态资源。

激活

一旦Service Worker被成功的注册或安装,第三步就是激活。
在这时候,Service Worker将会随着新的页面加载而开始工作。
它不能与已经加载的页面交互,所以Service Worker只有在用户第二次与应用程序交互或重新加载已经打开的页面时才有用。

self.addEventListener('activate', (event) => { //...
});
复制代码

这个事件的一个很好的用例是清理旧的缓存和与旧版本相关的旧版本,这些旧版本在新版本的Service Worker中没有使用。

更新一个Service Worker

要更新一个Service Worker,你只需要改变其中一个字节。当注册的代码运行的时候,它将被更新。
只要一个Service Worker被更新了,直到所有加载了旧Service Worker的页面都被关闭,它才会出现。
这确保了不会在应用或者页面已经运行的进程上出现任何问题。
刷新页面是不够的,旧的worker仍然在运行,它还没有被移除。

请求事件

当一个资源在网络上被请求时就触发了一个请求事件
这就让我们在发起网络请求时能够查看缓存。
例如,下面的代码片段使用缓存API来检查所请求的URL是否已经存储在缓存的响应中。如果已经缓存,就会返回缓存的响应。反之,它执行获取请求并返回它。

self.addEventListener('fetch', (event) => {event.respondWith( caches.match(event.request) .then((response) => { if (response) { //entry found in cache return response } return fetch(event.request) } ) )
})
复制代码

后台同步

后台同步允许将传出的连接延迟到用户拥有一个工作网络连接。
这是确保用户能够使用离线应用的关键,当连接打开时,队列服务器端更新(而不是展示一个无休止的spinning wheel来试图得到一个信号)。

navigator.serviceWorker.ready.then((swRegistration) => { return swRegistration.sync.register('event1')
});
复制代码

下面的代码在service worker中监听事件。

self.addEventListener('sync', (event) => { if (event.tag == 'event1') { event.waitUntil(doSomething()) }
})
复制代码

doSomething()返回一个promise。如果失败了,另一个同步事件将被安排自动重试,直到成功。
这也允许应用程序在有可用连接的情况下尽快更新服务器上的数据。

推送事件

在service worker允许web应用程序向用户提供本机推送通知。
Push和Notifications是两种不同的概念和技术,组合应用来实现我们所熟知的消息推送。Push提供了允许服务器向 service worker发送信息的机制,而Notifications是service worker向用户显示信息的方式。
因为service workers在应用停止的时候仍可以运行,它们可以监听推送事件。接着向用户显示信息,并更新应用状态。
推送事件是由一个后端发起,并通过浏览器推送服务。
下面是一个web worker如何侦听传入推送事件的示例:

self.addEventListener('push', (event) => { console.log('Received a push event', event) const options = { title: 'I got a message for you!', body: 'Here is the body of the message', icon: '/img/icon-192x192.png', tag: 'tag-for-this-notification', } event.waitUntil( self.registration.showNotification(title, options) )
})
复制代码

关于控制台日志的说明:

如果你在service worker中有任何控制台消息,确保您打开了由Chrome Devtools提供的保存日志功能。
另外,因为service worker在加载页面之前就开始操作了,并且控制台在加载页面之前将被清除,所以你讲不能再输出中看到任何日志。

[译] Service workers:PWA应用背后的英雄相关推荐

  1. Notification with Service Workers push events

    系列文章: Service Workers 和离线缓存 Notification with Service Workers push events (本文) PWA:添加应用至桌面及分享 Notifi ...

  2. 深入浅析Service Workers

    本篇文章给大家介绍一下JavaScript API - Service Workers.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 相关推荐:<编程入门> servi ...

  3. html5的service worker,GitHub - w3c/ServiceWorker: Service Workers

    What's going on here? Service workers are a new browser feature that provide event-driven scripts th ...

  4. 送RTX 4090!黄仁勋对话ChatGPT背后的英雄,GTC 2023 AI大会来了!

    点击下方卡片,关注"CVer"公众号 AI/CV重磅干货,第一时间送达 大家好,我是 Amusi!今天给大家介绍的是 GTC 2023 .GTC 是全球人工智能领域行业盛会,也是规 ...

  5. 前端开发的workers——web workers、share workers和service workers

    文章目录 突破单线程的瓶颈WEB WORKERS 兼容性 私有worker "杀死"workers 错误调试 异步在worker的表现 共享的shareWorkers servic ...

  6. 稳定支撑千万级月活,华为日历背后的英雄

    摘要:华为日历月活高达数千万,这使其对支撑业务的数据库提出了巨大挑战:高并发场景下,数据库如何实现快速扩容?海量数据运行,如何确保业务稳定性? 本文分享自华为云社区<稳定支撑千万级月活,华为日历 ...

  7. Service Workers让网站动态加载Webp图片

    Service Workers加载webp图片 每个图片加载请求可以通过accept获取是否支持webp格式,例如如下图 利用这一点,我们可以判断支持webp图片,就使用webp图片.我们需要注册一个 ...

  8. 使用 workbox 协助构建 PWA 应用

    使用 workbox 协助构建 PWA 应用 1. 说明 workbox 是 GoogleChrome 团队推出的一套解决方案,提供站点离线访问能力,可以更方便.更简单的解决 Service Work ...

  9. PWA之 Service worker

    渐进式 Web 应用(Progressive Web Apps,也被称为 PWAs)是 Web 技术方面一项令人兴奋的创新.PWA 混合了多项技术,能够让 Web 应用的功能类似于原生移动应用.它为开 ...

最新文章

  1. java postdelayed_你真的懂Handler.postDelayed()的原理吗?
  2. composer 更新版本
  3. HTML form 标签的 action 属性
  4. register_chrdev_region源码理解
  5. LIVE555再学习 -- testOnDemandRTSPServer 源码分析
  6. ubuntu下进程kidle_inject致使编译软件很慢
  7. 男人必看,男性排毒同样重要 - 生活至上,美容至尚!
  8. android 引用路径,android – ClassLoader引用了未知路径:/ data...
  9. 给所有想从事软件研发的年轻工程师的忠告与建议
  10. Oracle dmp文件导入
  11. Bash shell中的位置参数$#,$*,$@,$0,$1,$2...及特殊参数$?,$-等的含义 1
  12. iptables实现防火墙及NAT的基本功能----视频下载
  13. Android widget之CompoundButton
  14. 配置交叉编译工具链(imx6ull pro)
  15. 【端口扫描工具】mascan核心使用
  16. Flutter bottomSheet的使用
  17. qos 流控功能_QOS流量控制管理详解!
  18. 谷歌人工智能产生自我意识了!聊天记录曝光!机器真的只是机器吗?
  19. 写文案可以用什么软件?用来写文案的便签应用软件
  20. Mycat个人心得笔记(一)

热门文章

  1. [HttpPost]和[AcceptVerbs(HttpVerbs.Post)]区别
  2. ZOJ 38727(贪心)
  3. [转]VS2010安装说明及所有安装出错的解决办法
  4. LINQ学习(六):OrderBy/Group By子句
  5. 名词解释CPC、CPM、CPA.......[来源于网络]
  6. (转)IE的box模型显示bug
  7. javax.servlet.GenericServlet类(协议无关版本)
  8. hdu4885 有 限制的最短路
  9. 【C 语言】动态库封装与设计 ( Windows 动态库简介 | Visual Studio 调用动态库 )
  10. 【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 查找子弹数据的动态地址 | 查找子弹数据的静态地址 | 静态地址分析 | 完整流程 ) ★