實現 Web Push 通知 – 基礎 Progressive Web App 教學

實現 Web Push 通知 – 基礎 Progressive Web App 教學
實現 Web Push 通知 – 基礎 Progressive Web App 教學

用到的資源

Web Push 推播功能,這陣子很常看到的一個功能,如果一進入網站,看到網站要求顯示通知的權限,就代表這個網站有用這功能:

要求顯示通知的權限
要求顯示通知的權限

那通常,很多網站 UX 設計不良,在使用者根本就還搞不清楚這網站是幹麻的情況下就跳通知,所以大部份都直接按封鎖了吧 XD?

總之,在踩了幾個坑以後,終於完整的寫出了 Web Push 的功能。

完整是指會在桌機、安卓手機發出推播通知,並且點了會進到指定的頁面,同時在 Firebase 儲存發送訊息的記錄。

本篇用到的資源如下:

資料庫:Firebase Realtime Database
推播功能:Firebase Cloud Messaging
JS framework:Vue.js

Web Push 是 PWA 一個很重要的功能,關於 PWA,可以先參考之前寫的文章:

PWA 學習筆記 – 1:Cache、Workbox 基本使用
PWA 學習筆記 – 2:Workbox CLI
PWA 學習筆記 – 3:Workbox 參數
PWA 學習筆記 – 4:manifest.json

下面幾段步驟會用到前 3 篇筆記的東西,就不再另外解釋。


取得 FCM 金鑰

本篇是用 Firebase 的 Cloud Messaging功能(以下稱 FCM),去實作 Web Push。所以第一步是要先在 Firebase 上開一個專案。

以下截圖所用到的 Firebase 專案之後會刪掉,各種金鑰最後都不會存在,純示範用。

開完專案後,要取得推播金鑰,有了金鑰才能始用 FCM 的功能。

首先進到 Firebase 後台,點選齒輪後,再點選專案設定:

點選齒輪,再點專案設定
點選齒輪,再點專案設定

點擊 Cloud Messaging:

點擊Cloud Messaging
點擊Cloud Messaging

頁面往下拉,會看到一個「網路設定」的區塊,有一個「產生金鑰組」的按金,按下去:

按下產生金鑰組
按下產生金鑰組

就會產生一組 Web Push 用的金鑰,先存下來,Firebase Config 裡會用到:

存下推播憑證
存下推播憑證

新增 manifest.json、Firebase Config

manifest.json

取得金鑰後,第二步就是新增一個 manifest.json 的檔案,檔案內容大概如下:

最重要的是這一行:

"gcm_sender_id": "103953800507"

這行一定要有,key、value 是固定的,copy 貼上就行。

Firebase Config

建立一個首頁的檔案 index.html,在頁尾的部份引用 Firebase Config。

Firebase Config 一樣是後台有提供,點小齒輪,再點專案設定後,接著點代表 Web 的那個按鈕:

點選web button
點選 Web Button

就會出現 Config 了:

firebase config
Firebase Config

copy 以後貼到 index.html,另外也一併貼上 FCM 的引用,整合後如下:

最後一行的:

messaging.usePublicVapidKey('XXXXXXXXXXXXXXXXXXXX');

XXX 就是要替換成第一步拿到的 FCM 金鑰。


取得使用者的 token

簡單來說,Web Push 推播功能的流程如下:

  • 註冊 service-worker → 向使用者要求允許通知權限 → 
  • FCM 產生這個裝置的 token → token 寫進資料庫 →
  • 從後台使用 Web Push → Server 發 Web Push 到裝置上 →
  • 裝置上的 service worker 接收 → service worker 執行 notification

token 是每一個裝置會有的,之所以會以裝置為單位,而不是以使用者為單位,是因為每一個裝置都可以註冊service worker,而且每次存的 token 都會不同,所以一個使用者在桌機的 Chrome、Fireox,或是安卓手機的Chrome、Firefox,都有不同的 token。

假設王小明在桌機的 Chrome、Firefox,都按下了允許通知,在安卓手機的 Chrome、Firefox 也按了允許通知,那當我們按下發送推播後,王小明就會在 4 個地方收到相同的通知。因為是用裝置來區分的。

IOS 目前還不支援 Web Push。

2020.04.10更新:
今天看到 iZooto 的 一篇文章 上寫,在比對了一下 Can I Use 中的 service workers 支援情況,可以看到 IOS11.3 開始支援 Service Workers 了~但 Web Push 的功能只支援在 MAC,尚未支援到 iPhone上。


新增 sw.js

用 Workbox 新增一個 sw.js 檔案,把 Firebase 的 Config 放進去,程式碼如下:

如果推播裡要放公司的 Logo,那 Logo 的圖檔就要寫進快取檔案的清單裡,到時推播才有圖檔可以顯示。


註冊 sw.js、存 Cookies、存 Firebase

如果拿到的 token 不存在 Cookies 裡,用 Cookies 判斷是否拿過 token,那使用者就會存到 2 組以上的 token,在發推播時,就會收到相同的訊息多次。

當然,如果使用者清除了快取,就會有別種情況發生,最好的方式還是讓使用者登入會員後,再取得 token,把 token 跟會員綁一起,就不會有奇奇怪怪的情形出現。

以下為 JS code:

裡面有一行很重要:

messaging.useServiceWorker(xxx);

這是這次踩到的坑。

如果沒寫這行,就會發現網站存了 2 個 service worker,分別是 Firebase 的,以及我們自己的。這行可以讓 FCM 只存我們註冊的 sw.js,才可以在用 FCM 推播時,順利的執行推播及點擊後開啟指定的頁面。

成功的話,開啟 index.html,在開發人員工具的 Application → Service Workers,就會看見註冊了 sw.js 檔案:

註冊sw.js成功
註冊 sw.js 成功

註冊 sw.js 只能在 https 下,因此網域必須有S SL,不然會註冊失敗。

messaging.requestPermission()

這行會跟使用者要允許通知,使用者按下允許後,

messaging.getToken()

這行就會產生 FCM 的 token,之後就是存進 Firebase 跟 Cookies。

Firebase 上會看到以下:

firebase上存的token
Firebase 上存的 token

之後只要跑個迴圈,就可以一個個去發送 Web Push。


發送 Web Push

這邊新增一個 admin.html 來當做發送 Web Push 的後台介面,直接用 Vue.js 抓每個 input 的值。

web push admin demo
Web Push Admin Demo

Web Push 如果要判斷成效,直接用 Google Analytics 的 utm 參數就可以了,所以後台欄位有給 utm 用的 3 個主要參數。

不含樣式的原始碼文末會附上 GitHub 網址。

在發送 Web Push 時,還要填入伺服器的金鑰,這也是從 Firebase 後台可以拿到。點小齒輪 → 專案設定 → Cloud Messaging,第一個「伺服器金鑰」的值就是了:

取得伺服器金鑰
取得伺服器金鑰

發送 Web Push 的 JS 如下,寫在 admin.html 裡:

接收 Web Push

接受 Web Push 有 2 種情況:

  1. 使用者正開啟官網頁面
  2. 使用者沒有開啟官網頁面

第一種情況,是在 index.js 下寫一個 messaging.onMessage 的 function 處理。

第二種情況,是在 sw.js 下寫一個 messaging.setBackgroundMessageHandler 的 function 處理。

使用者正開啟官網頁面

官網正開啟的狀況下,屬於 JS 的 notification 功能,function 範例如下:

payload 就是傳來的值,點擊後要導到的頁面就用 location.href 來處理。

使用者沒有開啟官網頁面

使用者在上網,但沒有開啟官網的頁面,就是由之前註冊的 sw.js 處理,在 sw.js 加入以下:

click_action 是點擊後要開啟的頁面網址,但要另外寫一個 notificationclick 來處理。

這邊踩了一個坑,如果按照一般順序來寫,會先寫了 messaging.setBackgroundMessageHandler 後,再寫 notificationclick。然後就會發現,Chrome 上可以正常運作,但在 Firefox 上怎麼點就是不會開啟頁面。

Google 了很久,才看到這篇:service worker notificationclick event doesn’t focus or open my website in tab

click_action 是 Chrome 用的,如果 messaging.setBackgroundMessageHandler 先寫了,那 FCM 就會全部接收 Web Push 的功能,就不會讓原生的 notificationclick 事件被運作,因此 notificationclick 得寫在前,讓原生事件運作後,再執行 FCM 的事件。


補充資源

有了發送、接收,基本上 Web Push 就可以順利運作了。

要注意的是 Web Push 只接受在 https 以下運行。

最後附上學習時參考的教學文,以及本篇的 GitHub 原始碼。

從建 Firebase 就開始教學的(英文):Tutorial: Web Push notification using Firebase

建立 Service Worker Web Push Notification — (Firebase Push Notification實作紀錄)

Push Notification之成為訂閱用戶(Firebase實作)

Google 官方教學的原始碼:GitHub

Google 官方教學的功能示範:Notification Examples


PWA 學習筆記系列

Summary
PWA 學習筆記 - 5:用 Firebase 做 Web Push
Article Name
PWA 學習筆記 - 5:用 Firebase 做 Web Push
Description
探討 PWA 和 Web Push 的技術,學習如何透過這些現代 Web 技術來提升用戶體驗和參與度。本文提供了 PWA 和 Web Push 的基本概念、實作方法和實際應用案例。
Augustus
Let's Write
Let's Write
https://letswrite.tw/wp-content/uploads/2020/08/logo_512.jpg
訂閱
通知
guest

7 Comments
最舊
最新
Inline Feedbacks
看所有留言
JACK
JACK
4 年 之前

請問若使用虛擬主機,是否也可以實現此文章的推播功能(因無法在主機上安裝任何程式),感謝回覆。

Johnny Sung
Johnny Sung
回覆給  August
3 年 之前

用 firebase deploy 指令把程式上傳就可以了。虛擬主機沒有https功能無法做pwa驗證。還有Vue也可以上傳在虛擬主機使用。Node無法在虛擬主機使用,但是Firebase可以做Node的Host主機

koten
koten
3 年 之前

請問如果使用者關閉瀏覽器是否也可以收到推撥通知?

Johnny Sung
Johnny Sung
回覆給  August
3 年 之前

我很懷疑瀏覽器關掉無法推播,因為這不是PWA的精神,PWA是斷網也能看以前看過的。我看代碼都有對Firebase註冊過,所以在瀏覽器關著時,應該能推播。只是我試不出作者的功能,所以關瀏覽器試推播更無法驗證了。希望作者給個網址讓我們試試。或者給個確定沒問題的程式(firebaseConfig當然要放我們自己的)。啊如果真的關瀏覽器無法推播我也懶得再研究了,直接用原生iOS跟Android做了(這個我已經做了,只是不甘心被Apple綁架,想用PWA脫離它的魔掌)

Johnny Sung
Johnny Sung
3 年 之前

作者在medium.com發布的跟這篇不太一樣,這篇日期比較新,可是沒有留下Github原始碼。medium.com的原始碼一直做不出來,直到把index.html的script部分全部殺掉才沒發現錯誤輸出,但是仍然無法做到推播。如果作者把原始碼更新一下最好。還有請作者把它掛在Firebase的Host,這樣我們都可以直接使用在您的firebaseConfig下實驗推播功能(我們的裝置都變成你的可推播對象啦,沒啥不好吧!至少開放幾天讓我們測試一下)