原文地点:https:medium.freecodecamp.orgservice-workers-the-little-heroes-behind-progressive-web
原文地点:
https://medium.freecodecamp.org/service-workers-the-little-heroes-behind-progressive-web-apps-431cc22d0f16
作者:
Flavio Copes
择要:这篇文章简述service worker作为PWA中心手艺怎样完成资本缓存和音讯推送的功用,还协助读者明白service worker的生命周期。
Service worker是渐进式收集运用(Progressive Web Apps)的中心。它们协助我们完成原本是原生app才有资本缓存和音讯推送两大特征。
Service worker是你的网页与收集间的代办,它能够阻拦和缓存交游的收集要求。这能够协助你的运用制造一个离线环境下也能优越接见的用户体验。
起首引见一下web worker的观点。它是一个与指定网页相关联的JS文件,自力与主线程运转在一个特定的上下文环境中,如许就不会为了盘算数据去捐躯UI的机能,从而防止了壅塞的状况。而service worker是一种特别的web worker。
而恰是由于它是一个子线程,所以没法操纵DOM。一样也没法接见Local Storage API和XHR API。它只能经由过程Channel Messaging API和主线程通讯。
Service Worker能够与下面几个API协作:
- Promises
- Fetch API
- Cache API
只要在HTTPS协定下的网页里它们才会起作用。(不过不包括当地的收集要求,由于它们不须要坚持平安衔接。如许也轻易我们调试。)
背景历程
Service worker能够自力于与它关联的运用顺序运转,并且在这些顺序处于非活泼状况下仍能够吸收音讯。
让我来举几个场景:
- app处于背景非活泼状况下运转;
- app被封闭;
- 显现你网页的浏览器被封闭;
那末service worker将不受影响地继承事情。
Service worker的有效的处地点于:
- 它们能够看成缓冲层,处置惩罚收集要求和缓存离线所需的资本;
- 它们能够用来推送音讯。
Service worker只在须要的时刻运转,其他状况下都邑停止事情。
支撑离线
关于传统网页,离线状况下的用户体验异常蹩脚。假如用户没有联网,挪动端的web运用平常是直接停止事情。反观原生运用,会展现给用户一些友爱的提醒信息。
下面这张图是Chrome浏览器中离线网页显现的内容,明显这并不算是一个友爱的提醒信息:
或许唯一不错的处所是你能够经由过程点击恐龙来免费玩一个游戏,不过相信你很快就会变得不耐烦了。
不久之前,HTML5规范下的AppCache能够让web运用缓存离线资本,然则它缺少灵活性并且有一些令人困惑的行动,这也申明它没法胜任支撑离线这项事情。
而如今,service worker成了离线缓存的新规范。
那末,它完成哪些缓存呢?
装置时的预缓存
像图片、CSS文件和JS文件都邑在app的运用过程中反复用到。这些资本能够在app翻开的第一时间缓存好。
这也是所谓的APP壳架构( App Shell architecture)的基本。
缓存收集要求
我们运用Fetch API能够对效劳器返回的相应报文举行编辑,依据效劳器是不是可达来决议是不是运用缓存中的相应报文替代。
生命周期
一个service worker在启动前阅历了三步:
- 注册(Registration)
- 装置(Installation)
- 激活(Activation)
注册
注册阶段是关照浏览器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之前没有注册过或是须要更新的状况下进入注册阶段。
Scope
register函数须要一个scope参数来指明你的web运用被该service worker治理的文件地点途径。
这个参数的默认值是一切文件以及service worker文件父级目次下的一切子文件夹。所以假如你把service worker文件放在根目次下,它会治理全部web运用。而假如在某个子文件夹中,它只会治理该途径能够接见的网页。
下面这个例子经由过程指定scope参数为/notifications/
目次来注册一个service worker。
navigator.serviceWorker.register('/worker.js', {
scope: '/notifications/'
})
末端的/
异常重要,能够防止/notification
页面触发service worker。而假如写成下面如许:
{ scope: '/notifications' }
那末service worker就将一样作用于/notification
页面。
注重:service worker没法控制本身地点目次之外的文件。也就是说,假如service worker文件被放在/notification
文件夹下,它没法控制根目次/
或其他不属于/notification
的文件。
装置
假如浏览器发明一个service worker逾期或之前没有注册过,那末它将装置这个service worker。
self.addEventListener('install', (event) => {
//...
});
这是运用service worker初始化缓存,然后应用Cache API来缓存APP shell和静态资本的好时机。
激活
一旦service worker注册并装置胜利后 ,我们来到了第三阶段:激活。
这时候,service worker能够在加载新页面时最先事情。
它不能作用于激活前已加载过的页面,所以只要重启app或是革新已加载页面两种体式格局来使它事情。
self.addEventListener('activate', (event) => {
//...
});
监听这个事宜能够用来消灭旧缓存或者是删除新版service worker不须要的旧资本。
更新
你仅仅是修正一字节的文件就须要更新一次service worker。它会在注册的代码再次实行时被更新。
更新后的service worker只要在一切页面都被封闭后才最先替代之前的service worker事情。假如仅仅是革新页面是不会起作用的,由于之前的service worker依然在运转且没有被删除。
这类机制保证了更新不会让之前在运转的app或网页崩溃。
Fetch事宜
当浏览器发送收集要求时就会触发Fetch事宜。
我们借此能够在要求发送时搜检缓存中是不是已存储所需资本。
举个例子,下面的代码运用了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这个API将耽误该要求直到用户离开离线状况。
这保证了用户在离线状况下依然能够运用并操纵app,这些离线操纵会保存在行列中,以便在衔吸收集后向效劳端发出相应要求。(是不是是比展现一个无休止的loading图标要好多了?)
navigator.serviceWorker.ready.then((swRegistration) => {
//注册一个事宜event1
return swRegistration.sync.register('event1')
});
下面的代码是在service worker中监听这个事宜:
self.addEventListener('sync', (event) => {
if (event.tag == 'event1') {
event.waitUntil(doSomething())
}
})
doSomething()
返回一个promise。假如返回的promise被拒,另一个同步事宜被自动地最先重试操纵,直到返回一个胜利状况的promise。
这也使得app能够在联网时马上更新效劳器发来的数据。
音讯推送
Service worker使得web运用能够像原生一样推送音讯给用户。
事实上,推送和音讯关照是两个差别的观点,它们组合而成的手艺才是我们熟习的音讯推送。推送机制使得效劳器能够向service worker发送信息,然后service worker将信息展现给用户才是音讯关照。
由于service worker能够在app封闭后继承运转,所以它们能够一向监听推送事宜。然后它们能够发送音讯关照,或者是更新app的状况。
推送事宜会在后端经由过程浏览器推送效劳后启动,比如说Firebase的推送效劳。
下面的代码演示了web worker怎样监听push事宜:
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)
)
})
关于console.log
假如你的代码中包括console.log或是其他相似的控制台输出语句,务必翻开Chrome开发工具中的Preserve log
功用。
不然的话,由于service worker在网页加载前就最先实行,而此时控制台会被清空,所以你没法看到任何日记输出。
作者总结
异常感谢浏览本篇教程,事实上,关于PWA另有许多要进修的学问。假如您有什么看法迎接在下面批评。
译者注:主流浏览器最先逐步支撑service worker,今后PWA是不是会真的与原生势均力敌呢?将来怎样,我想如今多相识一点PWA的学问总不会坏事。
项目地点:
https://github.com/WhiteYin/translation