Service workers是Progressive Web Apps
的核心部分,容許緩存資源和Web推送通知等,以建立良好的離線體驗。它們充當Web應用程序,瀏覽器和網絡之間的代理,容許開發人員攔截和緩存網絡請求,並基於網絡的可用性採起適當的操做。javascript
一個service worker
在單獨的線程上運行,所以它是非阻塞的。這也意味着它沒法訪問主JavaScript
線程中可用的DOM和其餘API,好比cookie,XHR,Web存儲API(本地存儲和會話存儲)等。因爲它們被設計爲徹底異步,所以它們重度依賴promise來等待網絡請求的響應。css
出於安全考慮,service workers僅使用HTTPS運行,且不能在隱私瀏覽模式下使用。可是,在發出本地請求的時候,你不須要安全鏈接(這足以進行測試)。java
Service Workers是一種相對較新的API,僅受現代瀏覽器的支持。所以,咱們首先須要檢查瀏覽器是否支持該API:git
if('serviceWorker' in navigator) {
// Supported 😍
} else {
// Not supported 😥
}
複製代碼
在咱們開始緩存資源或攔截網絡請求以前,咱們必須在瀏覽器中安裝service worker
。因爲service worker
本質上是一個JavaScript
文件,所以能夠經過指定文件的路徑來註冊它。該文件必須能夠經過網絡訪問,而且只應包含service worker
代碼。github
你應該等待頁面加載完成,而後將service worker
文件路徑傳給navigator.serviceWorker.register()
方法:json
window.addEventListener('load', () => {
if ('serviceWorker' in navigator) {
// register service worker
navigator.serviceWorker.register('/sw-worker.js').then(
() => {
console.log('SW registration succesful 😍');
},
err => {
console.error('SW registration failed 😠', err)
});
} else {
// Not supported 😥
}
});
複製代碼
每次頁面加載時均可以運行上面的代碼,沒有任何問題;瀏覽器將決定是否已經安裝service worker
並相應地處理它。api
註冊生命週期包括三個步驟:promise
當用戶首次訪問您的網站時,會當即下載service worker
文件並嘗試安裝。若是安裝成功,則激活service worker
。在用戶訪問另外一個頁面後刷新當前頁面以前,service worker
文件中的任何功能都不可用。瀏覽器
一旦service worker
被安裝並激活了,它就能夠開始攔截網絡請求和緩存資源。這能夠經過監聽service worker
文件中瀏覽器發出的事件來完成。瀏覽器發出如下事件:緩存
install
active
。在安裝新版本以前,此事件可用於刪除過時的緩存資源。fetch
。資源能夠是任何東西:新的HTML文檔,圖像,JSON API,樣式表或者JavaScript文件,以及遠程位置上可用的任何內容。push
由Push API發送。你可使用此事件向用戶顯示通知。sync
。咱們能夠在安裝service worker
時監聽install
事件,以緩存當咱們離開網絡時須要爲網頁提供服務的特定資源:
const CACHE_NAME = 'site-name-cache';
self.addEventListener('install', event => {
event.waitUntil(
caches
.open(CACHE_NAME)
.then(cache =>
cache.addAll([
'favicon.ico',
'projects.json',
'style.css',
'index.js',
'https://fonts.googleapis.com/css?family=Open+Sans:400,700'
])
)
);
});
複製代碼
上面的例子中,代碼使用Cache API
將資源存儲在名爲site-name-cache
的緩存中。
self
關鍵字是一個只讀的全局屬性,service workers
使用它來訪問本身。
如今讓咱們監聽一個fetch
事件來檢查所請求的資源是否已經存儲在緩存中,若是找到則將其返回:
// ...
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
if (response) {
//found cached resource
return response;
}
return fetch(event.request);
})
);
});
複製代碼
咱們查找請求屬性標識的資源緩存條目,若是沒有找到,咱們會發送獲取請求。若是你也想緩存新的請求,能夠經過處理獲取請求的響應而後將其添加到緩存來完成,以下所示:
// ...
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
if (response) {
//found cached resource
return response;
}
// get resource and add it to cache
return fetch(event.request)
.then(response => {
// check if the response is valid
if (!response.ok) {
return response;
}
// clone the response
const newResponse = response.clone();
// add it to cache
caches.open(CACHE_NAME)
.then(cache =>
cache.put(event.request, newResponse)
);
// return response
return response;
});
})
);
});
複製代碼
安裝service worker
程序後,它將繼續運行,直到用戶將其刪除或者更新爲止。要更新service worker
,你須要作的就是在服務器上上傳新版本的service worker
文件。當用戶訪問你的站點時,瀏覽器將自動檢測文件更改(即便只有一個字節更改就足夠了),並安裝新版本。
就像第一次安裝同樣,只有當用戶導航到另外一個頁面或刷新當前頁面時,新的service worker
的功能才能使用。
咱們能夠作的事情就是監聽activate
事件,並刪除舊的緩存資源。如下代碼經過遍歷全部緩存並刪除與緩存名稱匹配的緩存來完成此操做:
// ...
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.map(cache => {
if (cache === CACHE_NAME) {
return caches.delete(cache);
}
})
);
})
);
});
複製代碼
以上就是service workers
的簡介了。若是你想了解更多,移步SerciceWorker Cookbook -- 這裏有一系列現代網站中使用service worker
的實用例子。
更多的內容,請戳個人博客進行了解,能留個star就更好了💨