你是否曾想讓某個網站能在發生重要事件時通知你?即使你並未開啟該網站也一樣能收到通知?可能有人用 WebRTC 打電話給你、或是收到即時簡訊,又或是一則重大金融消息。也許你所居住的城市剛發出緊急街道除雪或清掃通知。
反正有時候你就是會想知道某些事情發生的時間。
這就是 Firefox 44 現在提供的 Web Push 功能。
Web Push 推播起來是什麼樣子?
只要你正讓瀏覽器運作中,即使並未開啟某個網站,也同樣能接收網站發出的通知。這代表你甚至可以關閉電子郵件分頁,卻隨時知道有新訊息進入信箱。這對記憶體、裝置效能、電池電量都極有助益。
網站推播的通知與原生通知其實難以分辨。而 Mozilla 的「Service Worker Cookbook」則提供多個現成示範讓你親眼看看。
Web Push 的存取方式,與地理定位 (Geolocation) 或網路攝影機 (Webcam) 類似:在網站推播通知給使用者之前,Web Push 將明確要求可撤銷的許可。
隱私方面的考量呢?
Web Push 在運作時,需保持和 Push Service (像是訊息的中央轉接站) 之間的連線。各家瀏覽器都有自己的 Push Service 與其隱私防護設計:
- 為了避免跨網站關連性分析 (Cross-site correlation),針對你所使用的瀏覽器,各個網站都會收到不同的匿名 Web Push 識別碼。
- 為阻絕竊聽\取行為,內容 (Payload) 均加密之後送至僅由瀏覽器所持有的公開\私密金鑰。
- 如果你主動訂閱了 Web Push,Firefox 也只會連至 Push Service;可能是某個網站,或如 Firefox Hello 或 Firefox Sync 的瀏覽器功能。
而且使用者完全掌握自己的控制權,隨時可選擇是否開啟推播通知功能。而且只要進入,亦可取消之前許可過的網站。只要進入網頁訊息面板,或找到「偏好設定」→「內容」→「通知」,都能取消之前許可過的網站。
Web Push 怎麼運作的?
在此之前,大家都是依賴 App、電子郵件、文字訊息本身所傳送的即時通知。但現在 Web 也能辦到了!
Web Push 屬於 Service Worker 標準的延伸,也代表你能到 Mozilla 的 Service Worker Cookbook 中找到 Web Push 的絕妙展示。MDN 亦提供 Web Push 的相關說明文件。當然,如果你想直接取得原始碼,也能到 GitHub 上找到最新的「編輯草案 (Editor’s Draft)」。
去年 10 月時,另有一篇 Hacks 部落格文章介紹過 Web Push,簡單解釋了 Service Worker 及其對 Push 的關係。這裡稍微複習一下:
- 任一網站將透過瀏覽器註冊 1 組 Service Worker。Service Worker 為小型 JavaScript 程式,卻可擷取網路請求,甚至在上層網站關閉時仍可運作。
- Service Worker 註冊物件將可存取 pushManager 屬性。
- 使用 pushManager 的網站可取得現有的訂閱,甚或建立新的訂閱。
- 訂閱物件將存取訂閱的後設資料 (Metadata),其中包含瀏覽器廠商 Push Service上的專屬終端 (Endpoint) 網址。
不論網站的 POST 是何時抵達該終端,Push Service 均會傳送訊息到你的瀏覽器,讓正確的 Service Worker 接收推播事件。Service Worker 接著可顯示通知或執行其他動作。
Service Worker 的程式碼如下:
1 2 3 4 5 6 7 |
self.addEventListener('push', function(event) { event.waitUntil( self.registration.showNotification('Example Notification', { body: 'Hello, world!', }) ); }) |
另外,用以註冊 Service Worker 並取得許可的程式碼如下:
附註:此程式碼範例使用了 ES7 草稿中的 async/await 語法,也是目前看起來最整潔的範例。若要在正式運作的環境中使用此範例,請參閱同義的舊版 JavaScript 程式碼。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
async function registerForPush() { // Register the Service Worker let registration = await navigator.serviceWorker.register('service-worker.js'); // Check if we already have a subscription let subscription = await registration.pushManager.getSubscription(); // If not, try to subscribe. if (!subscription) { subscription = await registration.pushManager.subscribe(); } // Save the subscription data on our website's backend. await fetch('/save-push-endpoint', { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(subscription) }); // Done! Now our backend can send Push messages by POSTing to subscription.endpoint! } |
你同樣可到 Service Worker Cookbook 上觀看其他展示與其原始碼。如果你有點搞混了,就先從這裡著手吧。
其他 FAQ
使用者的終端網址會不會改變?
終端隨時都可能改變。雖然發生變化的情形並不常見,但你應隨時準備好處理 pushsubscriptionchange 事件。另外只要發生 getSubscription()
或 subscribe()
,也應檢查新的終端。
瀏覽器支援的情形為何?
截至本文發佈為止,Push 已可於 Firefox 桌面版上運作。在 Chrome 上需要額外設定,亦可達到部分支援。Microsoft 的 Edge 則將 Push 暫列為「考量中 (Under consideration)」。可參閱〈Can I Use?〉進一步了解。
該如何讓使用者取消訂閱 Push?
使用 subscription.unsubscribe() 函式即可。別忘了要更新自己的後端,才能停止寄送通知到舊的終端。
在 subscribe() 實際發生之前,我能檢查是否提示了使用者以取得許可嗎?
當然!只要呼叫 pushManager.permissionState() 就會回傳 1 組 Promise,顯示你目前的許可狀態為「granted
」、「denied
」,或是「prompt
」。
若你對 Push API 有任何問題或建議,甚至要提報臭蟲,都隨時歡迎告訴我們。
原文連結:Web Push Arrives in Firefox 44
參照: Trainspotting 系列文章:Firefox 44 | 部落格 | Mozilla Taiwan