——evilrescuer翻譯自Matt Gaunt
寫(xiě)的[Service Workers: an Introduction](收錄于 谷歌開(kāi)發(fā)者)(https://developers.google.com/web/fundamentals/primers/service-workers/)
豐富的離線體驗(yàn)坏瘩,定期后臺(tái)同步椭懊,推送通知 (一般這是原生app做的事)現(xiàn)在正在走向web. Service workers 提供了這些功能的技術(shù)基礎(chǔ)添谊。
一启盛、service worker是什么
service worker是一個(gè)腳本圆米,由瀏覽器在背后默默地運(yùn)行育瓜,獨(dú)立于web頁(yè)面。它給一些不需要頁(yè)面顯示和用戶操作的功能 開(kāi)啟了一扇新的大門(mén)。目前仑荐,它已經(jīng)包含了像推送通知 和 后臺(tái)同步這樣的功能。在未來(lái)纵东,service workers可能會(huì)支持其他功能粘招,如定期同步或者地理防護(hù)。這次我們介紹的它的核心功能是攔截和處理網(wǎng)絡(luò)請(qǐng)求篮迎,包括以編程方式管理響應(yīng)緩存男图。
地理防護(hù)(geofencing)是軟件程序中的一種功能,它運(yùn)用全球定位系統(tǒng)(GPS)或射頻識(shí)別(RFID)規(guī)定地理邊界甜橱。 地理柵欄是一種虛擬的邊界逊笆。 地理柵欄程序允許管理員設(shè)置觸發(fā)器,所以當(dāng)設(shè)備越過(guò)地理柵欄進(jìn)出管理員規(guī)定的邊界時(shí)岂傲,會(huì)有警告短信(SMS)或電子郵件發(fā)出难裆。
service worker之所以讓我們振奮人心,是因?yàn)樗С蛛x線體驗(yàn)镊掖,完全由開(kāi)發(fā)者控制乃戈。
在service worker之前,我們用一個(gè)API做離線體驗(yàn):AppCache亩进。但AppCache有一些問(wèn)題症虑,service workers在設(shè)計(jì)時(shí),就盡量避免了這些問(wèn)題归薛。
關(guān)于service worker谍憔,我們需要知道:
它是一個(gè) JavaScript 線程, 所以它不能直接接觸DOM. service worker 可以與一些頁(yè)面通信(這些頁(yè)面通過(guò)postMessage接口發(fā)出信息),而這些頁(yè)面可以操作DOM(如果需要的話)
Service worker 是一個(gè)可編程的網(wǎng)絡(luò)代理主籍,它允許你控制網(wǎng)絡(luò)如何從你的頁(yè)面發(fā)出請(qǐng)求习贫。
不使用時(shí)會(huì)停止運(yùn)行,在你下一次需要時(shí)又會(huì)重啟千元。所以苫昌,在一個(gè)service worker的
onfetch
和onmessage
處理函數(shù)里,你不能指望會(huì)有一個(gè)全局的service worker的狀態(tài)標(biāo)志幸海。如果你的確需要存儲(chǔ)并復(fù)用service worker的狀態(tài)祟身,它提供了一個(gè)API可以用來(lái)連接DB: IndexedDB APIService workers廣泛使用promises,所以如果你是一個(gè)promises小白物独,你需要停下來(lái)袜硫,先讀讀Promise的這篇文章:Promises介紹
service worker的生命周期
service worker有完全獨(dú)立于web頁(yè)面的生命周期。
如果你要給你的網(wǎng)站使用service worker议纯,你需要在指定的頁(yè)面的JavaScript中注冊(cè)父款。注冊(cè)service worker后溢谤,瀏覽器會(huì)默默地在背后安裝service worker瞻凤。
在安裝這一步中憨攒,你可能需要緩存一些靜態(tài)資源。如果所有這些文件緩存成功阀参,則service worker安裝成功肝集;相反,如果有文件下載緩存失敗蛛壳,則安裝步驟失敗杏瞻,此時(shí)service worker不會(huì)被激活 (沒(méi)裝上)。但是別擔(dān)心衙荐,稍后它還是會(huì)繼續(xù)安裝的捞挥。
安裝完成后,會(huì)啟動(dòng)激活步驟忧吟,此時(shí)非常適合用來(lái)處理 舊緩存砌函。
激活成功后,service worker會(huì)控制其范圍內(nèi)的所有頁(yè)面溜族。第一次注冊(cè)service worker的頁(yè)面讹俊,會(huì)等到頁(yè)面加載成功后,才會(huì)接受控制煌抒。一旦service worker在控制頁(yè)面仍劈,它只會(huì)有兩種狀態(tài):要么停止運(yùn)行,要么處理頁(yè)面中的fetch和message事件(當(dāng)頁(yè)面中有網(wǎng)絡(luò)請(qǐng)求或消息時(shí))寡壮。
下面這種圖顯示了service worker第一次安裝時(shí)的生命周期:
二贩疙、前提條件
1.瀏覽器支持
Chrome, Firefox and Opera支持Service workers。Microsoft Edge 現(xiàn)在也支持了(支持情況). 甚至連 Safari 也列入未來(lái)的開(kāi)發(fā)計(jì)劃诬像。最新的支持情況可以看這個(gè)網(wǎng)站: 《Serviceworker準(zhǔn)備好了嗎》屋群。
2.需要HTTPS
如果你要用service worker,本地開(kāi)發(fā)對(duì)HTTPS沒(méi)有要求坏挠。但是芍躏,如果你要部署到服務(wù)器,你必須要用HTTPS降狠。
service worker 可以劫持連接对竣、構(gòu)造和過(guò)濾返回。你可能可以正確地用這些特征榜配,但是中間人可不這么做否纬。為了防止中間人利用這些特點(diǎn),你可以為HTTPS頁(yè)面注冊(cè)service worker蛋褥。所以临燃,我們知道瀏覽器通過(guò)網(wǎng)絡(luò)接收到的service worker沒(méi)有被篡改過(guò)。
GitHub 頁(yè)面 就是建立在 HTTPS之上的, 所以是一個(gè)很好的放Demo的地方。
如果你想把HTTPS加到你到服務(wù)器里膜廊,你需要一個(gè)TLS證書(shū)乏沸,并在服務(wù)器上加上配置。配置多種多樣爪瓜,可以參考Mozilla的SSL配置生成器的最佳實(shí)踐蹬跃。
三、注冊(cè)service worker
在頁(yè)面上注冊(cè)铆铆,代碼如下:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}
以上代碼檢查service worker服務(wù)是否可用蝶缀,在一旦頁(yè)面load完成完成后,注冊(cè)/sw.js
薄货。
你可以在頁(yè)面加載后直接調(diào)用register()
翁都,瀏覽器會(huì)自動(dòng)處理service worker是不是已經(jīng)注冊(cè)過(guò)并且根據(jù)情況處理。
register()
的一個(gè)需要注意的點(diǎn)是service worker的文件位置谅猾。這個(gè)例子中荐吵,文件位置在域名的根位置底下。這說(shuō)明service worker的作用域是整個(gè)源赊瞬。換句話說(shuō)先煎,service worker會(huì)接受到這個(gè)域名下到所有fetch
事件。如果我們注冊(cè)到是/example/sw.js
這個(gè)位置巧涧,那service worker就只會(huì)接收到URL以/example/
開(kāi)頭(比如 /example/page1/
, /example/page2/
)的 fetch
事件
現(xiàn)在薯蝎,你可以看到 service worker已經(jīng)可用“可以通過(guò) chrome://inspect/#service-workers
和你的站點(diǎn)確認(rèn)占锯。
當(dāng)service worker第一次實(shí)施時(shí),如果你只是為了看生命周期缩筛,也可以通過(guò)chrome://serviceworker-internals
查看具體內(nèi)容消略。但以后可能會(huì)被chrome://inspect/#service-workers
取代。
在瀏覽器的隱私模式下瞎抛,service worker也可用艺演。但是,窗口之間是不互相影響的桐臊。隱私模式下的注冊(cè)和緩存胎撤,會(huì)在窗口被關(guān)閉時(shí)被清理。
四断凶、安裝service worker
注冊(cè)流程后伤提,我們說(shuō)說(shuō)安裝service worker的代碼。
最基礎(chǔ)的例子认烁,你需要給安裝事件一個(gè)callback函數(shù)肿男,并指定需要緩存的文件介汹。
self.addEventListener('install', function(event) {
// 處理安裝步驟
});
在callback函數(shù)內(nèi)部,我們需要注意:
- 開(kāi)啟緩存
- 緩存一些文件
- 檢查文件是否緩存成功
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
'/',
'/styles/main.css',
'/script/main.js'
];
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
這里舶沛,我們調(diào)用了caches.open()開(kāi)啟緩存痴昧。之后,我們調(diào)用cache.addAll()冠王,并傳入一個(gè)文件數(shù)組,指定了我們需要緩存的文件舌镶。這是一個(gè)promises鏈(caches.open() and cache.addAll())柱彻。event.waitUntil()方法通過(guò)promise得到安裝時(shí)間,安裝是否成功餐胀。
如果所有這些文件都被成功緩存哟楷,那service worker就被成功安裝上了。但是否灾,只要有一個(gè)文件下載失敗卖擅,整個(gè)安裝步驟就失敗了。這取決于你定義的這些文件墨技,所以你要小心對(duì)待這個(gè)文件列表惩阶,因?yàn)樗赡軐?dǎo)致你的service worker安裝不上。
這僅僅是一個(gè)例子扣汪,你也可以在安裝事件中處理其他任務(wù)断楷,或者不設(shè)置安裝事件的監(jiān)聽(tīng)器。
下篇會(huì)說(shuō)到如何返回一個(gè)緩存請(qǐng)求
和 如何更新service worker
以及 service worker的一些不好的東西
崭别。
《 Service Workers簡(jiǎn)介(二) 》