iT邦幫忙

2024 iThome 鐵人賽

DAY 7
1
JavaScript

可愛又迷人的 Web API系列 第 7

Day7. Web Notifications API 搭配 Service Workers 發送通知

  • 分享至 

  • xImage
  •  

在上一篇文章中,我們介紹了 Web Notification API 的基本用法。然而在實際應用中,僅僅依靠前端觸發通知是遠遠不夠的。為了建立一個功能完整、實用的通知系統,我們需要將前端與後端技術結合起來。

在透過後端 Server 發送通知之前,我們需要先了解 Service Workers。Service Workers 允許網頁在後台運行腳本,即使在使用者關閉網站的情況下,依然能夠接收和處理通知。我會跟大家介紹如何使用 Service Workers 來接收和顯示通知,包括註冊 Service Workers、在 Service Workers 中處理通知、透過開發者工具觸發通知,以及使用 Web Push 測試工具來模擬通知的接收過程。

使用 Service Workers 發送通知

Service Workers 可以讓使用者在關閉網站的情況下,依然讓該網站在後台執行腳本。

Service Workers 為網頁應用提供了強大的發送通知功能,讓使用者在未打開頁面的情況下接收通知。但我們會先使用開發者工具體驗 Service Workers,所以還是要把網頁打開才能使用唷。

註冊 Server Workers

首先要註冊 Server Workers,第 2 行註冊的 sw.js 是處理通知的檔案,必須放在網站的根目錄

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('sw.js')
    .then(registration => {
      console.log('Service Worker 註冊成功:', registration);
    })
    .catch(error => {
      console.error('Service Worker 註冊失敗:', error);
    });
}

在 Service Worker 中處理通知

新增檔案 sw.js,就是我們在註冊 Server Workers 時寫的那個檔案名稱,記得要放在網站的根目錄!重要~重要~重要

我監聽了四個事件:

  • installactive 透過 console.log() 的除錯訊息可以清楚知道事件的用途。
  • push :發送通知,等等會透過開發者工具的 Server Workers 來進行模擬。
  • notificationclick :點擊通知後要做的事情,上一篇文章的範例是點擊後會跳到一個網站,這裡也相同。
self.addEventListener('install', event => {
  console.log('Service Worker 安裝中...');
  self.skipWaiting();
});

self.addEventListener('activate', event => {
  console.log('Service Worker 已啟用');
});

self.addEventListener('push', event => {
  const data = event.data.json();
  self.registration.showNotification(data.title, {
    body: data.body,
    data: data.data
  });
});

self.addEventListener('notificationclick', event => {
  event.notification.close();
  const url = event.notification.data.url;
  event.waitUntil(
    clients.openWindow(url)
  );
});

透過開發者工具觸發通知

開發者工具面板選擇「Application」-> 「Service workers」可以看到我們已經安裝的服務

https://mukiwu.github.io/web-api-demo/img/6-3.png

其中一個欄位 Push 就是用來發送通知的事件。也就是我們在 sw.js 寫的這段程式碼

self.addEventListener('push', event => {
  const data = event.data.json();
  self.registration.showNotification(data.title, {
    body: data.body,
    data: data.data
  });
});

透過第二行 event.data.json() 得知我們要傳送的是一個 JSON,會傳送 data.title, data.body, 以及 data.data,所以 JSON 格式如下

{
  "title": "這是通知標題",
  "body": "這是通知內容",
  "data": {
    "url": "https://muki.tw/ngrok-err-ngrok-6024/"
  }
}

把 JSON 貼到 push 的輸入框後再按下「Push」按鈕,就能收到通知了

https://mukiwu.github.io/web-api-demo/img/6-4.png

在關閉網站的情況下接收通知

要在網站關閉的情況下測試發送通知,我們需要發送通知的服務來發送通知,通常需要用後端 Server 來做這件事,但我們先用一些現有的服務來做測試吧!

使用 Web Push 測試工具

有一些線上的 Web Push 測試工具可以幫助我們測試發送通知,今天要分享的是 Push Companion 網站的服務。
使用通知服務時,必須要有一組 public & private key,Push Companion 網站有直接提供我們測試的 key,所以暫時不需要申請。

這是我從 Push Companion 產生的 key:

Public Key

BDNzLXQEsMHUaZXjjyHzfi6HjLSg_6Vn1qskL3OYd-mAT6o_5Lggw4JSsNPkRKfA8Qbke2fHAgZMaALeTvShviY

Private Key

H2XUBO82HgMBrz93kNut5os7BTdTZWziY8qcAhKwgBQ

先來修改一下我們之前的程式碼,在 navigator.serviceWorker.register('sw.js') 後再呼叫 navigator.serviceWorker.ready,完整程式碼如下:

// 在 Push Companion 網站產生的 publickey
const publicKey = 'BDNzLXQEsMHUaZXjjyHzfi6HjLSg_6Vn1qskL3OYd-mAT6o_5Lggw4JSsNPkRKfA8Qbke2fHAgZMaALeTvShviY';

if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.register('sw.js')
    .then(registration => {
      console.log('Service Worker 註冊成功:', registration);
    })
    .catch(error => {
      console.error('Service Worker 註冊失敗:', error);
    });

  // 新增 ready()
  navigator.serviceWorker.ready.then(registration => {
    return registration.pushManager.subscribe({
      userVisibleOnly: true,
      // 新增 urlBase64ToUint8Array() 解析publickey
      applicationServerKey: urlBase64ToUint8Array(publicKey)
    });
  }).then(subscription => {
    console.log('推送訂閱資訊:', JSON.stringify(subscription));
  }).catch(error => {
    console.error('推送訂閱失敗:', error);
  });
}

function urlBase64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);
  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

回到網站打開 console 面板,可以看到印出的所有資訊。特別注意紅框處的地方,這是當發送訂閱成功時,會回傳的訂閱資訊,我們要將這段 JSON 複製起來,貼回 Push Companion 網站來發送通知。

https://mukiwu.github.io/web-api-demo/img/6-5.png

複製好訂閱資訊,就可以關閉網站囉!因為我們要測試當網站關閉時,是否能順利收到通知

在 Push Companion 網站上的 Subscription to Send To 欄位,貼上剛剛複製的訂閱資訊。在 Text to Send 欄位貼上我們要傳送的 JSON,就跟剛剛用開發者工具測試時的內容相同:

{
  "title": "這是通知標題",
  "body": "這是通知內容",
  "data": {
    "url": "https://muki.tw/ngrok-err-ngrok-6024/"
  }
}

https://mukiwu.github.io/web-api-demo/img/6-6.png

最後再按下「Send Push Message」按鈕,就可以看到通知囉!

小結

通過註冊 Service Workers,我們能夠在後台運行腳本,進而在網站關閉的情況下接收通知。希望這篇文章能幫助各位更好地理解與使用 Service Workers 來實作通知功能,有任何問題或想要討論的部分,都歡迎留言告訴我唷。


上一篇
Day6. 使用 Web Notifications API 幫網站加入通知功能
下一篇
Day8. Web Notifications API 結合 Google Cloud 的應用
系列文
可愛又迷人的 Web API20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言