微服务 人员协调开发
服务人员简介 (Introduction to Service Workers)
Service Workers are at the core of Progressive Web Apps, because they allow caching of resources and push notifications, two of the main distinguishing features that up to now set native apps apart.
服务工作者是渐进式Web应用程序的核心,因为它们允许缓存资源和推送通知,这是目前为止本机应用程序与众不同的两个主要区别功能。
A Service Worker is programmable proxy between your web page and the network, providing the ability to intercept and cache network requests, effectively giving you the ability to create an offline-first experience for your app.
Service Worker是您的网页和网络之间的可编程代理 ,提供了拦截和缓存网络请求的能力 ,有效地使您能够为您的应用创建离线优先的体验 。
It’s a special kind of web worker, a JavaScript file associated with a web page which runs on a worker context, separate from the main thread, giving the benefit of being non-blocking - so computations can be done without sacrificing the UI responsiveness.
这是一种特殊的Web工作程序 ,与在工作程序上下文中运行且与主线程分开的网页相关联的JavaScript文件,具有非阻塞性的优点-因此可以在不牺牲UI响应性的情况下进行计算。
Being on a separate thread it has no DOM access, and no access to the Local Storage APIs and the XHR API as well, and it can only communicate back to the main thread using the Channel Messaging API.
在单独的线程中,它没有DOM访问权限,也没有对本地存储 API和XHR API的访问权限,并且只能使用Channel Messaging API与主线程通信 。
Service Workers cooperate with other recent Web APIs:
服务工作者与其他最新的Web API协作:
And they are only available on HTTPS protocol pages, except for local requests, which do not need a secure connection for an easier testing.
它们仅在HTTPS协议页面上可用 ,本地请求除外,它们不需要安全连接即可进行更轻松的测试。
后台处理 (Background Processing)
Service Workers run independent of the application they are associated to, and they can receive messages when they are not active.
服务工作者独立于与其关联的应用程序运行,并且在它们不活动时可以接收消息。
For example they can work:
例如,它们可以工作:
when your mobile application is in the background, not active
当您的移动应用程序处于后台时 ,未激活
when your mobile application is closed, so even not running in the background
当您的移动应用程序关闭时 ,即使没有在后台运行
when the browser is closed, if the app is running in the browser
关闭浏览器时(如果应用程序正在浏览器中运行)
The main scenarios where Service Workers are very useful are:
服务工作者非常有用的主要方案是:
they can be used as a caching layer to handle network requests, and cache content to be used when offline
它们可以用作处理网络请求的缓存层 ,并可以缓存脱机时使用的内容
to allow push notifications
允许推送通知
A Service Worker only runs when needed, and it’s stopped when not used.
Service Worker仅在需要时运行,而在不使用时停止。
离线支援 (Offline Support)
Traditionally the offline experience for web apps has been very poor. Without a network, often web mobile apps won’t work, while native mobile apps have the ability to offer either a working version, or some kind of nice message.
传统上,Web应用程序的脱机体验非常差。 没有网络,Web移动应用程序通常将无法运行,而本机移动应用程序可以提供工作版本或某种形式的精美消息。
This is not a nice message, but this is what web pages look like in Chrome without a network connection:
这不是一个好消息,但这是没有网络连接的Chrome中的网页外观:
Possibly the only nice thing about this is that you get to play a free game by clicking the dinosaur, but it gets boring pretty quickly.
唯一可能的好处是,您可以通过单击恐龙来玩免费游戏,但很快就会感到无聊。
In the recent past the HTML5 AppCache already promised to allow web apps to cache resources and work offline, but its lack of flexibility and confusing behavior made it clear that it wasn’t good enough for the job, failing its promises (and it’s been discontinued).
最近,HTML5 AppCache已经承诺允许Web应用程序缓存资源并脱机工作,但是由于缺乏灵活性和令人困惑的行为,很明显它不能胜任这项工作,无法兑现其承诺(并且已终止。 )。
Service Workers are the new standard for offline caching.
服务工作者是离线缓存的新标准。
Which kind of caching is possible?
哪种缓存是可能的?
在安装过程中预缓存资产 (Precache assets during installation)
Assets that are reused throughout the application, like images, CSS, JavaScript files, can be installed the first time the app is opened.
可以在第一次打开应用程序时安装可在整个应用程序中重复使用的资产,例如图像,CSS,JavaScript文件。
This gives the base of what is called the App Shell architecture.
这提供了所谓的App Shell体系结构的基础 。
缓存网络请求 (Caching network requests)
Using the Fetch API we can edit the response coming from the server, determining if the server is not reachable and providing a response from the cache instead.
使用Fetch API,我们可以编辑来自服务器的响应,确定服务器是否不可访问,并从缓存中提供响应。
服务人员生命周期 (A Service Worker Lifecycle)
A Service Worker goes through 3 steps to be fully working:
服务人员要完成三个步骤,才能正常工作:
- Registration 注册
- Installation 安装
- Activation 激活
注册 (Registration)
Registration tells the browser where the server worker is, and it starts the installation in the background.
注册告诉浏览器服务器工作者在哪里,并在后台启动安装。
Example code to register a Service Worker placed in worker.js
:
注册位于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')
}
Even if this code is called multiple times, the browser will only perform the registration if the service worker is new, not registered previously, or if it has been updated.
即使多次调用此代码,浏览器也只会在服务工作者是新的,以前未注册或已更新的情况下执行注册。
范围 (Scope)
The register()
call also accepts a scope parameter, which is a path that determines which part of your application can be controlled by the service worker.
register()
调用还接受一个范围参数,该参数是确定服务工作者可以控制应用程序哪一部分的路径。
It defaults to all files and subfolders contained in the folder that contains the service worker file, so if you put it in the root folder, it will have control over the entire app. In a subfolder, it will only control pages accessible under that route.
它默认为包含服务工作者文件的文件夹中包含的所有文件和子文件夹,因此,如果将其放在根文件夹中,它将可以控制整个应用程序。 在子文件夹中,它将仅控制在该路由下可访问的页面。
The example below registers the worker, by specifying the /notifications/
folder scope.
下面的示例通过指定/notifications/
文件夹范围来注册工作程序。
navigator.serviceWorker.register('/worker.js', {
scope: '/notifications/'
})
The /
is important: in this case, the page /notifications
won’t trigger the Service Worker, while if the scope was
/
很重要:在这种情况下,页面/notifications
不会触发Service Worker,而如果范围是
{
scope: '/notifications'
}
it would have worked.
它会工作的。
NOTE: The service worker cannot “up” itself from a folder: if its file is put under
/notifications
, it cannot control the/
path or any other path that is not under/notifications
.注意:服务工作者无法从文件夹“自身”升级:如果将其文件放在
/notifications
,则它无法控制/
path或不在/notifications
下的任何其他路径。
安装 (Installation)
If the browser determines that a service worker is outdated or has never been registered before, it will proceed to install it.
如果浏览器确定服务工作者已过时或之前从未注册过,它将继续进行安装。
self.addEventListener('install', (event) => {
//...
});
This is a good event to prepare the Service Worker to be used, by initializing a cache, and cache the App Shell and static assets using the Cache API.
这是一个很好的事件,它通过初始化缓存来准备要使用的Service Worker,并使用Cache API 缓存App Shell和静态资产。
激活 (Activation)
The activation stage is the third step, once the service worker has been successfully registered and installed.
一旦成功注册并安装了服务工作者,激活阶段便是第三步。
At this point, the service worker will be able to work with new page loads.
此时,服务工作者将能够处理新的页面加载。
It cannot interact with pages already loaded, which means the service worker is only useful on the second time the user interacts with the app, or reloads one of the pages already open.
它无法与已加载的页面进行交互,这意味着服务工作者仅在用户第二次与应用程序进行交互或重新加载已打开的页面之一时才有用。
self.addEventListener('activate', (event) => {
//...
});
A good use case for this event is to cleanup old caches and things associated with the old version but unused in the new version of the service worker.
此事件的一个好用例是清除旧的缓存和与旧版本关联但在服务工作者的新版本中未使用的内容。
更新服务人员 (Updating a Service Worker)
To update a Service Worker you just need to change one byte into it, and when the register code is run, it will be updated.
要更新Service Worker,您只需要在其中更改一个字节,然后在运行注册码时,将对其进行更新。
Once a Service Worker is updated, it won’t become available until all pages that were loaded with the old service worker attached are closed.
更新Service Worker之后,只有关闭了所有附加了旧Service Worker的页面后,该服务才可用。
This ensures that nothing will break on the apps / pages already working.
这样可以确保在已经运行的应用程序/页面上没有任何损坏。
Refreshing the page is not enough, as the old worker is still running and it’s not been removed.
刷新页面是不够的,因为旧的工作程序仍在运行并且尚未删除。
取得事件 (Fetch Events)
A fetch event is fired when a resource is requested on the network.
当网络上请求资源时,将触发获取事件 。
This offers us the ability to look in the cache before making network requests.
这使我们能够在发出网络请求之前先查看缓存 。
For example the snippet below uses the Cache API to check if the request URL was already stored in the cached responses, and return the cached response if this is the case. Otherwise, it executes the fetch request and returns it.
例如,下面的代码片段使用Cache 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)
}
)
)
})
后台同步 (Background Sync)
Background sync allows outgoing connections to be deferred until the user has a working network connection.
后台同步允许将传出连接推迟到用户具有有效的网络连接之前。
This is key to ensure a user can use the app offline, and take actions on it, and queue server-side updates for when there is a connection open, instead of showing an endless spinning wheel trying to get a signal.
这是确保用户可以脱机使用该应用程序并对其执行操作,并在连接打开时将服务器端更新排队的关键,而不是显示试图获取信号的无休止的纺车。
navigator.serviceWorker.ready.then((swRegistration) => {
return swRegistration.sync.register('event1')
});
This code listens for the event in the Service Worker:
此代码在Service Worker中侦听事件:
self.addEventListener('sync', (event) => {
if (event.tag == 'event1') {
event.waitUntil(doSomething())
}
})
doSomething()
returns a promise. If it fails, another sync event will be scheduled to retry automatically, until it succeeds.
doSomething()
返回一个promise。 如果失败,则将安排另一个同步事件自动重试,直到成功。
This also allows an app to update data from the server as soon as there is a working connection available.
这也允许应用程序在存在可用连接后立即更新服务器中的数据。
推送事件 (Push Events)
Service Workers enable web apps to provide native Push Notifications to users, through the use of:
服务工作者可以通过以下方式使Web应用程序向用户提供本机推送通知:
Push and Notifications are actually two different concepts and technologies, but combined to provide what we know as Push Notifications. Push provides the mechanism that allows a server to send information to a service worker, and Notifications are the way service workers can show information to the user.
推送和通知实际上是两种不同的概念和技术,但结合起来提供了我们所知道的推送通知 。 推送提供了一种机制,允许服务器将信息发送给服务人员,而通知是服务人员可以向用户显示信息的方式。
Since Service Workers run even when the app is not running, they can listen for push events coming, and either provide user notifications, or update the state of the app.
由于Service Worker即使在应用程序未运行时也可以运行,因此他们可以侦听即将到来的推送事件,并提供用户通知或更新应用程序的状态。
Push events are initiated by a backend, through a browser push service, like the one provided by Firebase.
推送事件由后端通过浏览器推送服务(如Firebase提供的服务)启动。
Here is an example of how the service worker can listen for incoming push events:
这是服务工作者如何侦听传入的推送事件的示例:
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)
)
})
关于控制台日志的注释 (A note about console logs)
If you have any console log statement (console.log
and friends) in the Service Worker, make sure you turn on the Preserve log
feature provided by the Chrome DevTools, or equivalent.
如果Service Worker中有任何控制台日志语句( console.log
和friends),请确保您打开了Chrome DevTools提供的Preserve log
功能,或具有同等功能。
Otherwise, since the service worker acts before the page is loaded, and the console is cleared before loading the page, you won’t see any log in the console.
否则,由于服务工作者在加载页面之前会执行操作,并且在加载页面之前会清除控制台,因此控制台中不会显示任何日志。
微服务 人员协调开发