程式碼研究室:建構推播通知用戶端

Kate Jeffreys
Kate Jeffreys

本程式碼研究室會逐步說明如何建構推播通知用戶端。完成本程式碼研究室後,您將擁有一個可執行以下操作的用戶端:

  • 讓使用者訂閱推播通知。
  • 接收推送訊息,並以通知的形式顯示。
  • 取消使用者的推播通知訂閱。

本程式碼研究室著重於協助您透過實作學習,因此不會過多討論概念。請參閱「推播通知的運作方式」,瞭解推播通知的概念。

本程式碼研究室的伺服器程式碼已完成。您只會在本程式碼研究室中實作用戶端。如要瞭解如何實作推播通知伺服器,請參閱 程式碼研究室:建構推播通知伺服器

請查看 push-notifications-client-codelab-complete (原始碼),瞭解完整程式碼。

瀏覽器相容性

本程式碼研究室已知可搭配下列作業系統和瀏覽器組合使用:

  • Windows:Chrome、Edge
  • macOS:Chrome、Firefox
  • Android:Chrome、Firefox

這個程式碼研究室不支援下列作業系統 (或作業系統和瀏覽器組合):

  • macOS:Brave、Edge、Safari
  • iOS

設定

取得可編輯的程式碼副本

您在這些操作說明右側看到的程式碼編輯器,在本程式碼研究室中稱為「Glitch UI」

  1. 按一下「Remix to Edit」,即可編輯專案。

設定驗證方法

您必須先使用驗證金鑰設定伺服器和用戶端,才能使用推播通知。請參閱「簽署 Web Push 通訊協定要求」一文,瞭解原因。

  1. 在 Glitch 使用者介面中,依序按一下「Tools」和「Terminal」,即可開啟 Glitch 終端機。
  2. 在 Glitch 終端機中執行 npx web-push generate-vapid-keys。複製私密金鑰和公開金鑰值。
  3. 在 Glitch UI 中開啟 .env,並更新 VAPID_PUBLIC_KEYVAPID_PRIVATE_KEY。將 VAPID_SUBJECT 設為 mailto:test@test.test。所有這些值都應以雙引號括住。更新後,.env 檔案應如下所示:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. 關閉 Glitch 終端機。
  1. 開啟 public/index.js
  2. VAPID_PUBLIC_KEY_VALUE_HERE 替換為公開金鑰的值。

註冊 Service Worker

您的用戶端最終需要服務工作程式來接收及顯示通知。建議盡早註冊服務工作者。如需更多資訊,請參閱「接收並顯示推送的訊息做為通知」。

  1. 使用下列程式碼取代 // TODO add startup logic here 註解:
// TODO add startup logic here
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.register('./service-worker.js').then(serviceWorkerRegistration => {
    console.info('Service worker was registered.');
    console.info({serviceWorkerRegistration});
  }).catch(error => {
    console.error('An error occurred while registering the service worker.');
    console.error(error);
  });
  subscribeButton.disabled = false;
} else {
  console.error('Browser does not support service workers or push messages.');
}

subscribeButton.addEventListener('click', subscribeButtonHandler);
unsubscribeButton.addEventListener('click', unsubscribeButtonHandler);
  1. 如要預覽網站,請按下「View App」。然後按下「Fullscreen」圖示 全螢幕
  1. 按下 `Control + Shift + J` 鍵 (在 Mac 上為 `Command + Option + J` 鍵) 開啟開發人員工具。
  2. 再按一下 [Console] (控制台) 標籤即可。您應該會在控制台中看到 Service worker was registered. 訊息。

要求推播通知權限

請勿在載入網頁時要求使用者允許網站傳送推播通知。相反地,使用者介面應詢問使用者是否要接收推播通知。使用者明確確認 (例如按一下按鈕) 後,您就可以開始正式程序,從瀏覽器取得推播通知權限。

  1. 在 Glitch UI 中,按一下「View Source」即可返回程式碼。
  2. public/index.js 中,將 subscribeButtonHandler() 中的 // TODO 註解替換為以下程式碼:
// TODO
// Prevent the user from clicking the subscribe button multiple times.
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
  1. 返回應用程式分頁,然後按一下「訂閱推播」。瀏覽器或作業系統可能會詢問您是否要讓網站傳送推播通知。按一下「允許」 (或瀏覽器/作業系統使用的同義詞)。您應該會在控制台中看到訊息,指出要求是否已接受或拒絕。

訂閱推播通知

訂閱程序涉及與瀏覽器供應商控制的網路服務互動,這項服務稱為「推送服務」。取得推播通知訂閱資訊後,您必須將資訊傳送至伺服器,並讓伺服器將資訊長期儲存在資料庫中。如要進一步瞭解訂閱程序,請參閱「讓用戶訂閱推播通知」一文。

  1. 將下列醒目顯示的程式碼新增至 subscribeButtonHandler()
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
const registration = await navigator.serviceWorker.getRegistration();
const subscribed = await registration.pushManager.getSubscription();
if (subscribed) {
  console.info('User is already subscribed.');
  notifyMeButton.disabled = false;
  unsubscribeButton.disabled = false;
  return;
}
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY)
});
notifyMeButton.disabled = false;
fetch('/add-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(subscription)
});

userVisibleOnly 選項必須為 true。未來或許可以推送訊息,而不會顯示使用者可見的通知 (靜默推送),但由於隱私權問題,目前瀏覽器不允許這項功能。

applicationServerKey 值會依賴公用函式,將 base64 字串轉換為 Uint8Array。這個值用於伺服器和推播服務之間的驗證。

取消訂閱推播通知

使用者訂閱推播通知後,如果使用者改變心意,不再想接收推播通知,您的 UI 就需要提供取消訂閱的方式。

  1. unsubscribeButtonHandler() 中的 // TODO 註解替換為以下程式碼:
// TODO
const registration = await navigator.serviceWorker.getRegistration();
const subscription = await registration.pushManager.getSubscription();
fetch('/remove-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({endpoint: subscription.endpoint})
});
const unsubscribed = await subscription.unsubscribe();
if (unsubscribed) {
  console.info('Successfully unsubscribed from push notifications.');
  unsubscribeButton.disabled = true;
  subscribeButton.disabled = false;
  notifyMeButton.disabled = true;
}

接收推播訊息並以通知的形式顯示

如先前所述,您需要服務工作程式來處理從伺服器推送至用戶端的訊息接收和顯示作業。詳情請參閱「接收並顯示推送的訊息做為通知」。

  1. 開啟 public/service-worker.js,並以下列程式碼取代服務工作者的 push 事件處理常式中的 // TODO 註解:
// TODO
let data = event.data.json();
const image = 'https://cdn.glitch.com/614286c9-b4fc-4303-a6a9-a4cef0601b74%2Flogo.png?v=1605150951230';
const options = {
  body: data.options.body,
  icon: image
}
self.registration.showNotification(
  data.title, 
  options
);
  1. 返回應用程式分頁。
  2. 按一下「通知我」。你應該會收到推播通知。
  3. 請嘗試在其他瀏覽器 (甚至是其他裝置) 上開啟應用程式分頁的網址,完成訂閱工作流程,然後按一下「通知所有人」。您應該會在所有訂閱的瀏覽器上收到相同的推播通知。請參閱「瀏覽器相容性」,查看已知可用或無法使用的瀏覽器/作業系統組合清單。

您可以透過多種方式自訂通知。詳情請參閱 ServiceWorkerRegistration.showNotification() 的參數。

使用者點選通知時開啟網址

在實際情況中,您可能會使用通知來重新吸引使用者,並提示他們造訪您的網站。如要這麼做,您需要進一步設定服務工作站。

  1. 請將服務工作者的 notificationclick 事件處理常式中的 // TODO 註解替換為以下程式碼:
// TODO
event.notification.close();
event.waitUntil(self.clients.openWindow('https://web.dev'));
  1. 返回應用程式分頁,傳送另一則通知給自己,然後按一下通知。瀏覽器應會開啟新分頁並載入 https://web.dev

後續步驟