接續昨天的進度,我們已經pre-cache app.js這個檔案了,但是我們監聽fetch event時還時直接回應從網路fetch回來的結果,沒有從cache裡取出暫存的response(如下)。這樣沒有網路時,還是一樣的結果阿QQ
self.addEventListener('fetch', function(event) {
event.respondWith(fetch(event.request));
});
所以來更改一下event.respondWith()裡面的回傳內容吧:
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
if(response) {
return response;
} else {
return fetch(event.request);
}
})
);
});
一開始用caches.match()查詢要傳送的request是否存在sub cache中。若存在(也就是response不為null),就直接回傳cache中暫存的response;但response為null的話,則再透過網路用fetch request獲取該資源。
我們可以開啟developer tools中的Network查看app.js:(可以看到檔案是Service Worker從cache中取得的)
接著我們將index.html加入到cache中看看當網路offine時的結果:(記得在chrome developer tools的Service Worker點擊offline,這會切斷browser對外部網路的連線)
確認static cache有暫存到
咦!! 怎麼offline沒有從cache取回index.html頁面哩
這裡有一個地方需要注意!!!
事實上是有的,只是我們暫存的是cache.add('/index.html')[根部錄下的index.html頁面],所以url要改成localhost:8080/index.html才有response。為了讓首頁在offline時能正常瀏覽必須要再加上cache.add('/')。
讓我們把app shell中其他的資源加到cache中吧:(為了撰寫的方便性,這裡我改成使用addAll方法)
self.addEventListener('install', function(event) {
console.log('[Service Worker] Installing Service Worker ...', event);
event.waitUntil(
caches.open('static').then(function(cache) {
console.log('[Service Worker] Precaching App Shell');
cache.addAll([
'/',
'/index.html',
'/src/js/app.js',
'/src/js/feed.js',
'/src/js/promise.js',
'/src/js/fetch.js',
'/src/js/material.min.js',
'/src/css/app.css',
'/src/css/feed.css',
'/src/images/main-image.jpg',
'https://fonts.googleapis.com/css?family=Noto+Sans+TC&display=swap',
'https://fonts.googleapis.com/icon?family=Material+Icons',
'https://cdnjs.cloudflare.com/ajax/libs/material-design-lite/1.3.0/material.indigo-pink.min.css'
]);
})
);
});
把html、js、css和外部CDN的response暫存到cache後,看一下offline時畫面結果:
OK就整體畫面來說,不管是頁面、CSS還是圖片該暫存的都暫存到了,只是左上和右下的icon好像沒有出現QQ。為什麼?
針對這些material icons我在上面已經pre-cache https://fonts.googleapis.com/icon?family=Material+Icons 了,但是我們在Network好好的來看一下這段CDN request的回應結果:
結果發現在@font-face的src裡它又再去向另外一個外部url請求資源,我們當初並沒有把這些也暫存到,所以當然離線時icon是不會顯示出來的。
這裡我先留個伏筆,我會在實作Dynamic Caching時修復這個問題
到目前為止,我們考慮了pre-caching(明確定義要儲存在cache中的資源),但是如果我們想從cache中獲取其他任何外部資源,那它就會失敗。所以我們也可以「動態地將資源添加到cache中」,希望確保像是發出額外HTTP Request的icon或者如果用戶訪問了其他頁面,當再次訪問時,可以直接從cache中獲取。
當載入index.html、app.js文件時,都會發出一些fetch event,因為某些資源是透過外部導入來獲取的。在這種情形下我們可能希望先透過網路獲取該資源,然後使用cache API將獲取的資源暫存在cache中。因此,Dynamic caching意味著動態地向cache添加資源,我們可以在需要時才暫存它們。
Day09 結束!!