service workers是什么

2023-10-15 02:10
文章标签 service workers

本文主要是介绍service workers是什么,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是service workers,什么是service workers,如果你想知道什么是service workers,就让我来带你研究

认识service workers

什么是service workers

  • Chrome官方在线demo
    https://github.com/GoogleChrome/samples/tree/gh-pages/service-worker
  • Service Worker简介
    https://developers.google.com/web/fundamentals/primers/service-workers
  • Service Worker API - MDN
    https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
  • W3C 官方标准
    https://w3c.github.io/ServiceWorker/
  • Service Worker相关的资源
    https://jakearchibald.github.io

一个服务器与浏览器之间的中间人角色,如果网站中注册了service worker那么它可以拦截当前网站所有的请求,进行判断(需要编写相应的判断程序),如果需要向服务器发起请求的就转给服务器,如果可以直接使用缓存的就直接返回缓存不再转给服务器。从而大大提高浏览体验。

  • 基于web worker(一个独立于JavaScript主线程的独立线程,在里面执行需要消耗大量资源的操作不会堵塞主线程)
  • 在web worker的基础上增加了离线缓存的能力
  • 本质上充当Web应用程序(服务器)与浏览器之间的代理服务器(可以拦截全站的请求,并作出相应的动作->由开发者指定的动作)
  • 创建有效的离线体验(将一些不常更新的内容缓存在浏览器,提高访问体验)
  • 由事件驱动的,具有生命周期
  • 可以访问cache和indexDB
  • 支持推送
  • 并且可以让开发者自己控制管理缓存的内容以及版本

注意

Service worker运行在worker上下文 --> 不能访问DOM

它设计为完全异步,同步API(如XHR和localStorage)不能在service worker中使用

出于安全考量,Service workers只能由HTTPS承载

在Firefox浏览器的用户隐私模式,Service Worker不可用

其生命周期与页面无关(关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动)

一个简单的小demo

  1. 注册Service worker 在你的index.html加入以下内容
/* 判断当前浏览器是否支持serviceWorker */if ('serviceWorker' in navigator) {/* 当页面加载完成就创建一个serviceWorker */window.addEventListener('load', function () {/* 创建并指定对应的执行内容 *//* scope 参数是可选的,可以用来指定你想让 service worker 控制的内容的子目录。 在这个例子里,我们指定了 '/',表示 根网域下的所有内容。这也是默认值。 */navigator.serviceWorker.register('./serviceWorker.js', {scope: './'}).then(function (registration) {console.log('ServiceWorker registration successful with scope: ', registration.scope);}).catch(function (err) {console.log('ServiceWorker registration failed: ', err);});});}
  1. 安装worker:在我们指定的处理程序serviceWorker.js中书写对应的安装及拦截逻辑
/* 监听安装事件,install 事件一般是被用来设置你的浏览器的离线缓存逻辑 */
this.addEventListener('install', function (event) {/* 通过这个方法可以防止缓存未完成,就关闭serviceWorker */event.waitUntil(/* 创建一个名叫V1的缓存版本 */caches.open('v1').then(function (cache) {/* 指定要缓存的内容,地址为相对于跟域名的访问路径 */return cache.addAll(['./index.html']);}));
});/* 注册fetch事件,拦截全站的请求 */
this.addEventListener('fetch', function(event) {event.respondWith(// magic goes here/* 在缓存中匹配对应请求资源直接返回 */caches.match(event.request));
});

生命周期

Service Worker的初次运行生命周期流程如下图所示,从未注册开始主要分为Installed, Activated, IDLE 等阶段。

img

不同生命周期阶段转移的细节:

img

注册

在Service Worker被安装之前,首先需要在HTML页面内的脚本里注册server worker的脚本,即前面提到过的特定格式的JavaScript见(例如: sw.js)。注册这一步是在运行网页自身的脚本时告知浏览器:

这个页面是使用了Service Worker的,请加载指定路径的Service Worker的脚本并将它安装到当前域。

这一步本身不属于Service Worker的生命周期,因为它是需要在页面脚本里完成的,这和WebSocket比较类似。如下面的脚本(注意:它必须是HTML页面中script标签的一部分,而不是sw.js中的):

if ('serviceWorker' in navigator) {navigator.serviceWorker.register('/sw.js').then(function(registration) {// Registration was successfulconsole.log(':) Success. ', registration.scope);}, function(err) {// registration failed :(console.log(':( Failed. ', err);});
}

上面的代码为当前页面所在的域注册了sw.js,我们还可以使用***scope***为它的指定更为细分的范围。也就是说,只有发送往当前域中来自scope中指定子路径的请求才会被Service Worker拦截,其他路径的请求将不受影响。如下图代码,只有向”https://domain/app/“及其子路径作为url的请求才会被service-worker.js里绑定的事件响应。

navigator.serviceWorker.register('/service-worker.js', {scope: '/app/'
});

若scope未被指定,那么默认的scope是获取service worker脚本所在的同级域,及其响应的子域。

生命周期事件

Service Worker中的主要生命周期阶段的变化,是通过事件来通知脚本的,所以Serice Worker的脚本主要需要做的是为不同生命周期事件绑定好对应的处理器。核心的生命周期事件处理器如图示:

img

下载事件 (Dowload)

下载事件未在上图中标出,它发生在脚本注册阶段被触发且由浏览器处理: 1) 从指定路径下载service worker的脚本; 2) 完成脚本的解析,如果不符合service worker脚本的规范则不会触发安装事件; 3) 正确的脚本被安装到浏览器的Service Worker列表,被触发安装事件; 下载失败,解析失败或者初始化错误引发的错误也可以在浏览器的开发者工具 -> 应用 -> Service Worker列表看到,

img

安装事件 (Install)

在下载事件被浏览器响应完成后,安装事件是Service Worker生命周期中第一个被触发的,所以它非常重要。我们通常使用它来完成各种初始化任务,主要是资源的预加载、缓存以及持久化一些长期有效的状态。

这里主要被使用的是Cache API,监听到安装事件就可以预先拉取一些资源,并在应用缓存中存储它们并用给定的名字标识,参见下面的代码示例。在下文中有关于API的更详细的内容。

const CACHE_NAME = 'my-site-cache-v1';
const urlsToCache = [  // The list of resources to cache'/','/styles/main.css','/script/main.js'
];self.addEventListener('install', event => {// Perform install stepsevent.waitUntil(caches.open(CACHE_NAME).then(function(cache) {console.log('Opened cache');return cache.addAll(urlsToCache);}));
});

鉴于Service Worker本质上类似于Web Worker,它的资源加载完全独立于页面进程,所以它完全不会影响首屏渲染的性能。当然了,我们也完全不能预期在首次加载中就能受到应用缓存带来的优化。

激活事件 (activate)

当Service Worker已经就绪,可以控制页面请求并处理功能事件如fetch,pushsync,激活事件就会被触发,我们监听激活事件的处理器就可以响应。

self.addEventListener('activate', event => {console.log('V1 now ready to handle fetches!');
});

激活事件标志着从这之后的请求将被Service Worker接管,所以通常用于区分Service Worker接管前后的分隔。 但这不意味着当前这次有效完成".register()"的页面会受到Service Worker 管理,因为我们无法预测页面资源先获取完成还是激活事件先响应。

请求事件 (fetch)

fetch事件被触发于页面对网络发起任意请求,当然我们前面已经提过:1)必须在激活事件触发后service worker接管网络请求;2)请求的目标url必须位于注册的资源范围(scope)内。

来看一下这个 demo, 这里Service Worker劫持了"fetch"请求,但只在激活后才会生效:

  1. 当你第一次打开这个demo页面,你应该在等待后看到一张狗的图片,因为这个页面的标签指向的就是一张dog.svg。对这个图片的请求在完成Service Worker的注册之前就已经发出去了,响应的自然是狗的图片。
  2. 然后刷新页面,这一次我们看到的却是猫的剪影图片了,之后反复刷新都会是猫的图片。因为Service Worker已经完成了注册,开始接管对图片资源的HTTP请求,并将我们的请求换成它准备好的猫图了。

我们来看看SW的脚本里都做了什么:

// Caching the cat image when installing
self.addEventListener('install', event => {console.log('V2 installing…');// cache a horse SVG into a new cache, static-v2event.waitUntil(caches.open('static-v2').then(cache => cache.add('/cat.svg')));
});// Response the cat image when requesting dog.
self.addEventListener('fetch', event => {const url = new URL(event.request.url);  // serve the cat SVG from the cache if the request is// same-origin and the path is '/dog.svg'if (url.origin == location.origin && url.pathname.endsWith('/dog.svg')) {event.respondWith(caches.match('cat.svg'));}
});
  • 在安装事件中,service worker请求了猫图cat.svg并加入缓存,这是页面进程完全不知道的。
  • 而在fetch事件中,我们劫持了网络请求,当资源目标为狗图时,service worker没有乖乖地转发请求,而是从缓存列表取出猫图,回复给了页面。同样,我们的页面并不知道这个请求根本没有通过网络,而是被service worker返回的资源应付了。就会有这张猫图在页面的资源列表里被标注成了请求的dog.svg的奇妙效果:

img

在上面提到的Service Worker的开发这界面,我们可以通过点击"unregiter"来取消当前service worker脚本的注册,这样在下一次打开时虽然service worker会被再次注册,至少在那一次的页面我们见到的将还是狗图了。

这篇关于service workers是什么的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/214698

相关文章

UserWarning: mkl-service package failed to import

安装完成anaconda,并设置了两个环境变量  之后再控制台运行python环境,输入import numpy as np,提示错误 D:\InstallFolder\Anaconda3\lib\site-packages\numpy\__init__.py:143: UserWarning: mkl-service package failed to import, therefore

jdbc连接数据库使用sid和service_name的区别 ?

问题描述: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor The Connection descriptor used by the client was: 10.12.162.84:1521:xxxx  oracle数据的tnsnames.ora中配置的是:SERVICE

Spring 注解(@Repository 、@Service 和 @Controller )

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller 。         在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层 、业务层 和控制层 相对应。虽然目前这 3 个注释和 @

Android 接收系统广播,开机启动Service,SMS,Battery

本文内容摘自《疯狂Android讲义 第3版》李刚 著 自动开启的Service: package shortcut.song.com.myapplication;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;im

设计之道:ORM、DAO、Service与三层架构的规范探索

引言: 实际开发中,遵守一定的开发规范,不仅可以提高开发效率,还可以提高项目的后续维护性以及项目的扩展性;了解一下本博客的项目设计规范,对项目开发很有意义 一、ORM思想 ORM(Object-Relational-Mapping)在对象模型和关系型模型之间做一个映射(转换)。 目的是为了解决面向对象编程语言的发展和关系型数据库的发展不匹配的问题 可以理解为: 将Java中的数据结

nacos Spring cloud 报错 URI is not absolute、service not found、502 bad gateway

- 服务没找到,请加入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency> - 如果是 "URI is not absolute" , 将URL变成固定的字符串,例如

Service相关汇集(可续)

官译:Service 001、Service是什么 Service 是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行。

java利用Jersey创建RESTful service

http://www.toutiao.com/a6346735102701289729/?tt_from=mobile_qq&utm_campaign=client_share&app=explore_article&utm_source=mobile_qq&iid=5840657922&utm_medium=toutiao_ios

虚拟机无法打开网卡 service network restart失败

问题描述 命令重启网卡服务,结果报错如下:Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details 根据提示,输入systemctl stat

apk系列------app加service遇到的问题

问题1:在androidmanefist.xml加入service的定义之后出现了exported service does not require permission 回答: 你的service不需要权限设置,内部就可以调用,你把加的限制或者intent-filter去掉试试 问题2:apk安装进去之后遇到出错:PhoneFactory.getDefaultPhone must be