今天筆記內容是要來了解 Service Worker 的 fetch 事件。
第一次進入網站,因為 Service Worker 還沒有被註冊,而我們的 request 會在 Service Worker 註冊完成進入到 activate 狀態之前就發送,所以通常第一次進入網站不會攔截到任何的 fetch 事件。
我們來簡單實作看看,首先要註冊 Service Worker,接著發送 request,Service Worker 的 fetch 事件才有辦法接收到 request 資料。
HTML - index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PWA Demo</title>
</head>
<body>
<p> \{^_^}/ hi! This's PWA Demo. </p>
<ul id="list"></ul>
<script>
// 註冊 Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
</script>
<script>
const list = document.getElementById('list');
// 接著發送 request
fetch('http://localhost:3000/people')
.then(res => {
return res.json();
})
.then(json => {
list.innerHTML = json
.map(item => `<li>${item.name}</li>`)
.join('');
})
</script>
</body>
</html>
在範例 index.html
的檔案裡、寫了一段 script 載入 Service Worker 檔案去註冊 Service Worker,並且執行 fetch http://localhost:3000/people
送出 HTTP request。
到 fetch 事件裡面去 console 對應的 request 資訊
// fetch
self.addEventListener('fetch', event => {
console.log('now fetch!');
console.log('event.request:', event.request);
console.log('[ServiceWorker] Fetch', event.request.url);
});
查看 console,已成功取得 request 資訊,代表網頁有送出 HTTP request:
藉由 Service Worker 的 fetch 事件,我們可以成功攔截到 request 相關資訊。
先來講一下為什麼要處理攔截到的 Request/Response?
我們攔截到 Request 之後,預期會回傳 Response,
而必須將每一次的 Response 做 cache,才可以在離線的時候做存取,達成 PWA 的目標,所以在 fetch 的事件中,都要去處理 Request 並回傳 Response。
Request 要透過 respondWith
方法、才能將 response 回傳給網頁。
例如
// fetch
self.addEventListener('fetch', event => {
event.respondWith(
// magic goes here
);
});
如果網站失去網路連線,我們可以回傳 cached 過的 response,提供網站資料、讓使用者能夠持續進行瀏覽,所以要如何將 cached 過的 response 資料做回傳?
我們需要透過 caches.match() 這個方法裡面帶一個參數,放入 request,就可以去配對 event.request。
範例程式碼如下:
this.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
);
});
找到哪一個 cache 是已被 cached 之後,接著再回傳對應的 response。
this.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function (response) {
return response;
});
);
});
假如在下列的範例程式碼中,回傳的 response 是 undefined
,那麼代表這個 request 沒有被 fetch 過。
因為我們必須事先保存資料,讓網站即使在離線的狀態下,仍然能夠進行瀏覽,所以要用 fetch 把 HTTP request 真的送出,在 response 後進行 cache。
self.addEventListener('fetch', event => {
const dataUrl = 'http://localhost:3000';
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request).then(res =>
// 存 caches 之前,要先打開 caches.open(dataCacheName)
caches.open(dataCacheName)
.then(function(cache) {
// cache.put(key, value)
// 下一次 caches.match 會對應到 event.request
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
去判斷 Request 有沒有被 cached ? 做對應處理如下,確保網站能夠離線運作。
本人小小筆記,如有錯誤或需要改進的部分,歡迎給予回饋。
我將會用最快的速度修正,m(_ _)m。謝謝