iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 11
1

如果今天用戶沒有拜訪過某個頁面(舉例來說我的PWA中help.html),那麼在網路離線時,我們之前所做的dynamic caching是無法fetch到這個資源並暫存的。所以遇到這種情況應該要再製作一個「連線錯誤的頁面」,當在執行動態暫存發生錯誤時會Fallback的頁面。

BTW ~~ 之所以這樣做只是為了要增加更好的User Experience

我在根目錄新增一個offline.html,頁面怎麼設計這邊並不是重點我就不多加描述,這邊我是直接拿index.html來修改。重點是記得在sw.js中「將offline.html加入到pre-cache的陣列中」,並且變更「fetch event listener」和「CACHE_STATIC_NAME的版本號」:

var CACHE_STATIC_NAME = 'static-v10'; // 記得每次修改相關的靜態資源時要更新版本
self.addEventListener('fetch', function(event) {
    event.respondWith(
        caches.match(event.request).then(function(response) {
            if(response) {
                return response;
            } else {
                return fetch(event.request).then(function(res) {
                    return caches.open(CACHE_DYNAMIC_NAME).then(function(cache) {
                        cache.put(event.request.url, res.clone());
                        return res;
                    })
                }).catch(function(err) {
                    return caches.open(CACHE_STATIC_NAME).then(function(cache) {
                        return cache.match('/offline.html');
                    });
                });
            }
        })
    );
});

這裡我將策略修改成先去cache查看有無暫存,若有直接回傳。沒有則再去fetch這個資源,並把它暫存到dynamic cache中。不過如果用戶是在沒有網路連線第一次拜訪某頁面的話,則回傳offline頁面給用戶。

看一下離線時,第一次拜訪help頁面的結果:

Cache with Network Fallback Strategies

是不是有人會覺得我目前寫得這個cache策略是自己亂掰的XDD /images/emoticon/emoticon37.gif
事實上這個策略的名稱叫「Cache with Network Fallback Strategies」。

這張流程圖可以清楚的了解我之前所寫的cache策略:

  1. 首先當我們載入首頁並且要fetch其他資源時,Service Worker就會監聽並攔截這些request。
  2. 先去cache中尋找是否該request有pre caching或是dynamic caching,若有則直接回傳該資源的response。
  3. 沒有的話則再透過網路去fetch該資源。
  4. 把從外部fetch回來的資源「request」和「response」添加到dynamic cache中,下次載入相同資源時就可以直接從cache中獲得,並同時將該資源回傳到頁面。

缺點:
這個策略會將所有存取到的資源添加到cache中,這其實對於「會經常更新的資源」是不太適合的。因為我們預設的情形下不會有網路連線的,「經常更新的資源」可能會由於來不及更新cache而導致還是返回舊版本cache中的資源。

接著來了解一下還有哪些其他cache strategies吧!! /images/emoticon/emoticon12.gif

Cache Only Strategies

這個策略是最簡單的XDD,我個人覺得也是最難應用在現實場景中。

  1. 一開始一樣由service worker攔截fetch request。
  2. 接著直接到cache尋找該request是否在pre-cache的靜態資源中。(這種策略下就不會有dynamic caching了,因為用戶根本不能透過網路來獲取外部資源)
  3. 如果在cache中的話就回傳。

code也是非常地簡單,這裡我就不多做說明:

// Cache-Only
self.addEventListener('fetch', function(event) {
    event.respondWith(
        caches.match(event.request)
    );
});

Network With Cache Fallback Strategies

這個策略比起我原本寫的策略又更合理了一些XDD

  1. Service Worker一樣攔截fetch資源的request。
  2. 接著先直接透過網路來獲取該資源,成功則回傳response到頁面中並將其暫存到dynamic cache中。
  3. 若fetch失敗的話(也就是沒有網路連線),才去cache(static and dynamic cache)中尋找相對應的資源response。
  4. cache中有的話才回傳到頁面。

看一下code該怎麼寫吧:(首先用fetch API透網路來獲取資源,接著成功的話暫存到dynamic cache。失敗的話則透過catch()來從cache中尋找相對應的暫存資源)

self.addEventListener('fetch', function(event) {
    event.respondWith(
        fetch(event.request).then(function(res) {
            return caches.open(CACHE_DYNAMIC_NAME).then(function(cache) {
                cache.put(event.request.url, res.clone());
                return res;
            })
        }).catch(function(err) {
            return caches.match(event.request)
        })
    );
});

缺點:
如果今天只是網路狀況不穩定的話,這個策略就變得很沒有效率。假如網路需要等帶60秒以上才有回應,那用戶就必須等待這麼多的時間,之後才會跳到cache中去尋找資源,這樣使用者體驗是非常差的。

明天繼續來看還有哪些Strategies更適合我們的PWA project/images/emoticon/emoticon69.gif

Day11 結束!! /images/emoticon/emoticon34.gif


上一篇
[Day10] 在Service Worker中實作Caching(Part3)
下一篇
[Day12] Service Worker進階Caching實作(Part2)
系列文
你應該要知道的新一代Web技術---漸進式網頁(PWA)29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言