原文

丰富的离线体验、定期后台同步、推送通知——通常需要原生应用程序的功能——正在网络上出现。 Service Worker 提供了所有这些功能所依赖的技术基础。

What is a service worker

Service Worker 是浏览器在后台运行的脚本,与网页分开,为不需要网页或用户交互的功能打开大门。 今天,它们已经包含推送通知和后台同步等功能。 将来,Service Worker 可能会支持其他功能,例如定期同步或地理围栏。 本教程中讨论的核心功能是拦截和处理网络请求的能力,包括以编程方式管理响应缓存。

这是一个如此令人兴奋的 API 的原因是它允许您支持离线体验,让开发人员完全控制体验。

在 Service Worker 之前,还有一个 API 可以为用户提供网络离线体验,称为 AppCache。 服务工作者旨在避免 AppCache API 的许多问题。

Service Worker 的注意事项:

它是一个 JavaScript Worker,所以它不能直接访问 DOM。

相反,Service Worker 可以通过响应通过 postMessage 接口发送的消息与其控制的页面进行通信,如果需要,这些页面可以操作 DOM。

Service Worker 是一个可编程的网络代理,允许您控制如何处理来自您的页面的网络请求。

它在不使用时终止,并在下一次需要时重新启动,因此您不能依赖 Service Worker 的 onfetch 和 onmessage 处理程序中的全局状态。 如果您需要在重启后保留和重用某些信息,Service Worker 确实可以访问 IndexedDB API。

The service worker life cycle

Service Worker 的生命周期与您的网页完全分开。

要为您的站点安装 Service Worker,您需要在页面的 JavaScript 中注册它。注册 Service Worker 将导致浏览器在后台启动 Service Worker 安装步骤。

通常在安装步骤中,您需要缓存一些静态资产。如果所有文件都被成功缓存,那么 Service Worker 就会被安装。如果任何文件无法下载和缓存,则安装步骤将失败并且 Service Worker 将不会激活(即不会被安装)。如果发生这种情况,请不要担心,它下次会再试一次。但这意味着如果它确实安装了,您就知道缓存中已经有了这些静态资产。

安装后,将执行激活步骤,这是处理旧缓存管理的绝佳机会,我们将在 Service Worker 更新部分进行介绍。

在激活步骤之后,Service Worker 将控制其范围内的所有页面,尽管第一次注册 Service Worker 的页面在再次加载之前不会受到控制。一旦 Service Worker 处于控制状态,它将处于两种状态之一:Service Worker 将被终止以节省内存,或者它会处理从您的页面发出网络请求或消息时发生的 fetch 和 message 事件。

下面是首次安装时 Service Worker 生命周期的过度简化版本。

Register a service worker

要安装 Service Worker,您需要通过在您的页面中注册它来启动该过程。 这会告诉浏览器您的 Service Worker JavaScript 文件所在的位置。

if ('serviceWorker' in navigator) {window.addEventListener('load', function() {navigator.serviceWorker.register('/sw.js').then(function(registration) {// Registration was successfulconsole.log('ServiceWorker registration successful with scope: ', registration.scope);}, function(err) {// registration failed :(console.log('ServiceWorker registration failed: ', err);});});
}

此代码检查 service worker API 是否可用,如果可用,则在页面加载后注册 /sw.js 中的 service worker。

您可以在每次页面加载时调用 register() 而不用担心; 浏览器会判断 service worker 是否已经注册并相应地处理它。

register() 方法的一个微妙之处是 service worker 文件的位置。 在这种情况下,您会注意到 service worker 文件位于域的根目录。 这意味着服务工作者的范围将是整个源。

换句话说,这个 Service Worker 将接收该域上所有内容的 fetch 事件。 如果我们在 /example/sw.js 注册 Service Worker 文件,那么 Service Worker 只会看到 URL 以 /example/ 开头的页面(即 /example/page1/、/example/page2/)的 fetch 事件。

现在,您可以通过转到 chrome://inspect/#service-workers 并查找您的站点来检查 Service Worker 是否已启用。

您可能会发现在隐身窗口中测试您的 Service Worker 很有用,这样您就可以关闭并重新打开,因为之前的 Service Worker 不会影响新窗口。 一旦该窗口关闭,从隐身窗口中创建的任何注册和缓存都将被清除。

Install a service worker

在受控页面启动注册过程后,让我们转向处理安装事件的服务工作者脚本的观点。

对于最基本的示例,您需要为安装事件定义回调并决定要缓存哪些文件。

self.addEventListener('install', function(event) {// Perform install steps
});

在我们的安装回调中,我们需要执行以下步骤:

  1. 打开缓存。
  2. 缓存我们的文件。
  3. 确认是否缓存了所有必需的资产。
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = ['/','/styles/main.css','/script/main.js'
];self.addEventListener('install', function(event) {// Perform install stepsevent.waitUntil(caches.open(CACHE_NAME).then(function(cache) {console.log('Opened cache');return cache.addAll(urlsToCache);}));
});

在这里你可以看到我们用我们想要的缓存名称调用 caches.open() ,之后我们调用 cache.addAll() 并传入我们的文件数组。 这是一个承诺链(caches.open() 和 cache.addAll())。 event.waitUntil() 方法接受一个 promise 并使用它来知道安装需要多长时间,以及它是否成功。

如果所有文件都成功缓存,则将安装 Service Worker。 如果任何文件下载失败,则安装步骤将失败。 这允许您依赖您定义的所有资产,但确实意味着您需要小心您决定在安装步骤中缓存的文件列表。 定义一长串文件会增加一个文件无法缓存的可能性,从而导致您的 Service Worker 无法安装。

这只是一个示例,您可以在安装事件中执行其他任务或完全避免设置安装事件侦听器。

Cache and return requests

现在您已经安装了 Service Worker,您可能想要返回缓存的响应之一,对吗?

安装 Service Worker 并且用户导航到不同页面或刷新后,Service Worker 将开始接收 fetch 事件,示例如下。

self.addEventListener('fetch', function(event) {event.respondWith(caches.match(event.request).then(function(response) {// Cache hit - return responseif (response) {return response;}return fetch(event.request);}));
});

这里我们定义了 fetch 事件,在 event.respondWith() 中,我们从 caches.match() 中传入了一个 promise。 此方法查看请求并从您的 Service Worker 创建的任何缓存中查找任何缓存结果。

如果我们有匹配的响应,我们返回缓存的值,否则我们返回调用 fetch 的结果,如果可以从网络中检索到任何东西,它将发出网络请求并返回数据。 这是一个简单的示例,使用我们在安装步骤中缓存的任何缓存资产。

如果我们想累积缓存新请求,我们可以通过处理 fetch 请求的响应然后将其添加到缓存中来实现,如下所示。

self.addEventListener('fetch', function(event) {event.respondWith(caches.match(event.request).then(function(response) {// Cache hit - return responseif (response) {return response;}return fetch(event.request).then(function(response) {// Check if we received a valid responseif(!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 two streams.var responseToCache = response.clone();caches.open(CACHE_NAME).then(function(cache) {cache.put(event.request, responseToCache);});return response;});}));
});

更多Jerry的原创文章,尽在:“汪子熙”:

Service Worker 概念简介相关推荐

  1. Service Worker 的一个实战例子

    关于 Service Worker 概念的例子,请参考我之前的这篇文章.本文是实战. 本地新建一个 html 文件,该文件里加载一个 Service worker 的实现: <html> ...

  2. 借助Service Worker和cacheStorage缓存及离线开发

    一.缓存和离线开发 说得HTML5离线开发,我们通常第一反应是使用html5 manifest缓存技术,此技术已经出现很多年了,我以前多次了解过,也见过一些实践案例,但是却从未在博客中介绍过,因为并不 ...

  3. Service worker 的概念和用法

    Service workers 本质上充当 Web 应用程序.浏览器与网络(可用时)之间的代理服务器.这个 API 旨在创建有效的离线体验,它会拦截网络请求并根据网络是否可用采取来适当的动作.更新来自 ...

  4. 网易云课堂 Service Worker 运用与实践

    前言 本文首先会简单介绍下前端的常见缓存方式,再引入Service Worker的概念,针对其原理和如何运用进行介绍.然后基于google推出的第三方库Workbox,在产品中进行运用实践,并对其原理 ...

  5. 简单的了解下 Service Worker

    前言 本文首先会简单介绍下前端的常见缓存方式,再引入serviceworker的概念,针对其原理和如何运用进行介绍.然后基于google推出的第三方库workbox,在产品中进行运用实践,并对其原理进 ...

  6. 初识Service Worker

    当下PWA比较火,而Service Worker是实现PWA的一项关键技术,今天我们一起了解下关于Service Worker的一些基础知识和适用场景. 什么是Server Worker 我们先来看一 ...

  7. Service Worker 图片加载失败处理

    Service Worker 图片加载失败处理 参考文档 git clone https://gitee.com/wjj0720/Service-Worker.git 运行 npm i npm sta ...

  8. Service Worker 全面进阶

    腾讯云技术社区-掘金主页持续为大家呈现云计算技术文章,欢迎大家关注! 作者:villainthr Service Worder 是用来代替 manifest,用来生成缓存的效果的.以前吭哧吭哧的学 m ...

  9. 进程控制概念简介 多线程上篇(三)

    进程控制 进程的基本数据信息是操作系统控制管理进程的数据集合,这些信息就是用来控制进程的,此处我们说的进程控制就是进程的管理. 比如进程有状态,那么进程的创建.终止,状态的切换,这都不是进程自主进行的 ...

最新文章

  1. JetBrains打造的开发神器,一套代码适应多端!
  2. mysql的索引本质是一颗_一文揭开Mysql索引本质
  3. python 布尔值 bool( ) 与逻辑运算符
  4. android jni 释放资源
  5. c3p0依赖导入失败问题(在使用到c3p0中的ComboPooledDataSource类的时候报错,依赖爆红)
  6. MTK 驱动开发(54)---MTK-thermal.conf温度参数修改的方法
  7. ElasticSearch索引的基本操作命令
  8. linux串口环形缓冲区,能不能讲解下串口环形缓冲区的概念?
  9. jqueryui时间插件_jQueryUI工具提示插件
  10. wordpress网站被挂马处理
  11. DOS计算机设置登录密码,如何在DOS里设置计算机密码
  12. Faster:一个高效就地更新的并发键值存储
  13. 魅族手机flyme服务器不响应,魅族手机你绝对不知道的小技巧,魅族Flyme系统超实用!...
  14. Windows Azure Active Directory (1) 前言 - 基于声明的验证和授权
  15. PHP GD库 生成图片水印
  16. 自由运动物体的运动代码
  17. window10 电脑总是会从睡眠模式中自动唤醒
  18. Vulnhub-theEther
  19. 冰蝎加密 WebShell 过杀软
  20. c语言中出现nan错误,c语言中浮点运算的inf和nan错误

热门文章

  1. linux 下使用 tc 模拟网络延迟和丢包
  2. php http头设置相关信息
  3. SQL数据库 - (二)关系数据库
  4. Ubuntu下载gitea
  5. xshell有大量打印时,显示信息不全
  6. Ecos笔记--2014/5/3
  7. 多项式相乘与相加演示
  8. 什么是依赖注入?(听来的一个笑话)
  9. 除了CRUD也要注意IO
  10. zookeeper 源码阅读(2)