iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 5
2

來看看Service Worker怎麼監聽事件/images/emoticon/emoticon28.gif

我們可以在sw.js file裡,開始監聽一些比較基本的事件。

// 當service worker在「安裝階段」時會觸發此事件
self.addEventListener('install', function(event) {
    console.log('[Service Worker] Installing Service Worker ...', event);
});

// 當service worker在「激活階段」時會觸發此事件
self.addEventListener('activate', function(event) {
    console.log('[Service Worker] Activating Service Worker ...', event);
    return self.clients.claim();   // 加上這行是為了確保service worker被正確載入和激活,不加也行
});

接著我們reload網頁,看一下console,咦?
結果發現怎麼只有顯示出安裝階段的log,激活階段哩!!!
還有照理來說不是應該安裝和激活階段完成後才算註冊完成嗎!!!


這邊先回答第二個問題,其實瀏覽器顯示出來的log並不一定保證與執行順序是一致的。不過這邊以我的project來說,正確執行順序是在「app.js註冊service worker後」 --> 「觸發install event」 --> 「觸發activate event」 --> 「印出Service Registered log」。

第一個問題的答案我們從下面這張圖來說:

由於我們的PWA網頁視窗一直開著,導致即使我們今天reload頁面,網頁為了避免crash掉還是繼續使用舊版本的service worker。所以現在我們必須要關掉目前的視窗,在新視窗重新開啟我們的網頁,來看一下結果。

嘿嘿 現在我們的執行順序和log都有正常顯示出來惹 /images/emoticon/emoticon07.gif

除了監聽service worker生命週期的event,what else?

現在我們來監聽fetch事件,「fetch事件」是當今天我們的html頁面載入外部JS、CSS的CDN或是內部的其他檔案資源時觸發。此外,我們也可以把service worker看成一個具有類似network proxy的功能,能夠將從外部獲取的response進行攔截並做更進一步的處理(舉例來說,之後我會根據網路是否有連線,來決定要從Cache拿資料或是直接回傳結果)。讓我們來看一下code:

self.addEventListener('fetch', function(event) {
    console.log('[Service Worker] Fetch something ...', event);
    event.respondWith(fetch(event.request));
});

之後我就會用event.respondWith方法來根據網路是否連線,來實現我們PWA離線使用的功能

設置App Install Banner

什麼是App Install Banner?/images/emoticon/emoticon19.gif
就是當用戶進到我們網頁時,會跳出一個「是否要將此網頁加到主畫面上」的通知,這讓用戶不需要自行手動加入,讓使用者體驗更順暢。另外我們也可以決定install banner要甚麼時候被觸發,這些在google developer page都有詳細的教學

在官方文件中有說到只要滿足某些條件,app install banner就會自動跳出通知

所以這邊對於我的project我想要設置成當用戶按下右下角plus icon時,就代表他已經要開始使用我們的PWA,此時跳出加到主畫面通知是比較合適的時機。

首先因為我們的PWA已經滿足官網所定義的那些條件,所以目前app install banner會自動跳出通知,但是我要在設置成當用戶按下icon時才會跳出。

來吧~~所以我要在app.js,要監聽一個「beforeinstallprompt」事件,它會在chrome browser跳出通知前被觸發:

let deferredPrompt;

window.addEventListener('beforeinstallprompt', function(event) {
    console.log('beforeinstallprompt fired');
    event.preventDefault();  // 取消預設的直接跳出通知設定
    deferredPrompt = event;  // 將監聽到的install banner事件傳到deferredPrompt變數
    
    return false;
});

接下來就在feed.js的openCreatePostModal function(也就是點擊plus icon時,會觸發執行的函式)中加入下面的code:

if(deferredPrompt) {   // 確定我們有「攔截」到chrome所發出的install banner事件
    deferredPrompt.prompt();   // 決定要跳出通知

    // 根據用戶的選擇進行不同處理,這邊我指印出log結果
    deferredPrompt.userChoice.then(function(choiceResult) {
      console.log(choiceResult.outcome);
      
      if(choiceResult.outcome === 'dismissed'){
        console.log('User cancelled installation');
      }else{
        console.log('User added to home screen');
      }
    });
    deferredPrompt = null; // 一旦用戶允許加入後,之後就不會再出現通知
}

來看一下在手機上的實際畫面吧!! /images/emoticon/emoticon34.gif

Day05 結束!!/images/emoticon/emoticon10.gif


上一篇
[Day04] Service Worker の 基礎介紹(Part1)
下一篇
[Day06] 複習一下Jacvascript中的 Promise 和 Fetch(Part1)
系列文
你應該要知道的新一代Web技術---漸進式網頁(PWA)29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言