PWA 筆記 - 推播通知實作
這是一個簡單的 Progressive Web App(PWA)範例,主要實作以下兩個功能:
- 推播通知(Push Notification)
- PWA 安裝體驗(Add to Home Screen)
最近剛好在工作上遇到類似需求,便趁機做了這個小專案,作為整合 PWA 和推播功能的 MVP,方便自己測試與驗證技術可行性,也為後續可能的擴充做準備。
同時也想藉這個機會,跟公司內部進行簡單的 Demo 與分享,讓大家對相關技術有初步了解,因此衍生出這個範例專案。
NOTE:本專案純屬個人練習用途,內容與公司實際專案無關,亦不涉及任何業務邏輯或商業模型。
專案目標
該專案主要在展示如何使用 Next.js 和相關技術來實現 PWA 的功能,特別是推播通知的功能。
功能概述
- 推播通知:用戶可以訂閱推播通知,並在收到通知時顯示在設備上。
- PWA 安裝:用戶可以將應用安裝到桌面,提供類似原生應用的體驗。
- 通知管理:用戶可以開啟或關閉通知訂閱,並查看通知內容。
技術棧
- web-push:用於推播通知的服務。
- next-pwa:Next.js 的 PWA 套件。
- 自動協助產生 service-worker.js:透過 next-pwa 自動生成並管理 service-worker.js。
- 支援自訂 service-worker.js,你可以在 worker/index.js 定義自己的推播通知邏輯。
主要文件和結構
- README.md:提供了如何生成 VAPID keys 和設置環境變數的指南。
- generateManifest.mjs 和 generateResizedImages.mjs:用於生成 PWA 所需的 manifest 和圖標。
- components/:包含各種 UI 元件,如通知開關、安裝按鈕等。
- hooks/:包含自定義的 React hooks,用於註冊 Service Worker 和監聽通知。
- worker/index.js:Service Worker 的實現,用於處理推播通知。
環境設定
0. 確認本身主機是否有開啟瀏覽器通知的設定
在測試推播通知功能前,請先確認電腦系統已允許瀏覽器顯示通知。 以 Mac + Chrome 為例,請到 系統設定 → 通知 → Google Chrome,開啟「允許通知」選項,並確保其他相關通知權限(例如顯示於通知中心、播放通知聲音等)也已啟用,這樣才能正常接收到推播訊息。
1. 產生 VAPID Keys
首先需要產生推播通知所需的 VAPID (Voluntary Application Server Identification) keys:
2. 設置環境變數
將生成的 VAPID keys 設置到環境變數中:
注意:請確保 NEXT_PUBLIC_BASE_PATH 的設定與 ./public/manifest.json 中 icon 的 src 路徑前綴一致,否則 PWA 圖示可能無法正確顯示。
3. 產生 manifest.json 以及所需圖片
該指令會產生 manifest.json 以及所需圖片,並放置於 public 資料夾下
4. 安裝並執行專案
與推播通知功能相關的資料夾結構
推播通知功能流程
1. Service Worker 註冊
檔案位置: hooks/use-register-service-worker.ts
描述: 當 Component On Mount 時,這個 hook 會註冊一個 service worker。它會檢查瀏覽器是否支持 service worker,並在未註冊的情況下進行註冊。
2. 通知權限和訂閱
檔案位置: components/notification-toggle.tsx
描述:
- 這個 Component 管理通知訂閱狀態
- 它向用戶請求通知權限,並使用 service worker 訂閱推播通知
- 它使用
useNotificationListenerhook 來監聽來自 service worker 的消息
3. 監聽通知
檔案位置: hooks/use-notification-listener.ts
描述: 當通知被授權時,這個 hook 會監聽來自 service worker 的消息,並向用戶顯示消息。
4. Service Worker 推播事件處理與 Badge 管理
檔案位置: worker/index.js
事件監聽器:
push: 處理傳入的推播事件,顯示通知並更新應用程式徽章notificationclick: 處理通知點擊事件,根據需要聚焦或打開新窗口
描述: service worker 監聽推播事件,顯示通知並管理 app badge 的數量(unread count)。
5. 發送通知
檔案位置: components/notification-sender.tsx
描述: 這個 Component 提供發送通知的用戶界面。它接收一個 endpoint 並使用 sendNotification 動作發送通知。
6. 通知相關的 API
檔案位置: actions/notification.ts
描述: 包含伺服器端的通知發送功能。它使用 web-push 庫來發送推播通知,並設定 VAPID 金鑰用於推播通知的加密和身份驗證。主要功能包括:
- 接收通知訊息和目標 endpoint
- 使用 web-push 發送通知到指定的 endpoint
- 處理錯誤並回傳適當的回應
7. 清除應用程式徽章
檔案位置: components/read-notification.tsx
描述: 這個 Component 提供一個按鈕來清除 app badge 的數量,使用 navigator.clearAppBadge API。
NOTE:Android 不支援
8. 彈出通知
檔案位置: components/ui/sonner.tsx
Component: Toaster
描述: 使用 sonner 來顯示彈出通知。