我們可以在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都有正常顯示出來惹
現在我們來監聽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?
就是當用戶進到我們網頁時,會跳出一個「是否要將此網頁加到主畫面上」的通知,這讓用戶不需要自行手動加入,讓使用者體驗更順暢。另外我們也可以決定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; // 一旦用戶允許加入後,之後就不會再出現通知
}
來看一下在手機上的實際畫面吧!!
Day05 結束!!