程式碼研究室:建構推播通知伺服器

Kate Jeffreys
Kate Jeffreys

本程式碼研究室會逐步說明如何建構推播通知伺服器。 完成程式碼研究室後,您的伺服器將具有:

  • 追蹤推播通知訂閱 (即伺服器會建立 新的資料庫記錄下來 在用戶端停用時刪除現有的資料庫記錄)
  • 將推播通知傳送至單一用戶端
  • 傳送推播通知給所有已訂閱的用戶端

本程式碼研究室著重於協助您從工作中學習,不會 一些概念退房日 推播通知的運作方式 瞭解推播通知的概念

本程式碼研究室的用戶端程式碼已完成。 。如要瞭解 推播通知用戶端,請參閱「程式碼研究室:建構推播通知 用戶端

請參閱 push-notifications-server-codelab-complete 的說明 (資料來源) 就能看到完整程式碼

瀏覽器相容性

本程式碼研究室介紹的作業系統和瀏覽器組合如下:

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

已知本程式碼研究室「無法」與下列作業系統搭配使用 (或作業系統和瀏覽器組合):

  • macOS:Brave、Edge、Safari
  • iOS

應用程式堆疊

  • 伺服器是以 Express.js 為基礎。
  • web-push Node.js 程式庫 會處理所有推播通知邏輯
  • 訂閱資料會使用 lowdb 寫入 JSON 檔案。

您不必使用上述任何技術導入推播通知。 我們之所以選擇這些技術,是因為這類技術可提供可靠的程式碼研究室體驗。

設定

取得程式碼的可編輯副本

這類操作說明右側的程式碼編輯器會稱為 Glitch UI

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

設定驗證方法

必須先完成設定,才能使用推播通知 驗證金鑰和用戶端。 請參閱「簽署網路推送通訊協定要求」一節。 瞭解原因。

  1. 依序點選「Tools」和「Terminal」,開啟 Glitch 終端機。
  2. 在終端機中執行 npx web-push generate-vapid-keys。複製私密金鑰 和公開金鑰值
  3. 開啟「.env」,並更新「VAPID_PUBLIC_KEY」和「VAPID_PRIVATE_KEY」。組合 VAPID_SUBJECTmailto: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 替換為公開金鑰的值。

管理訂閱項目

您的用戶端會處理大部分的訂閱流程。主要 伺服器使用者必須先儲存新的推播通知訂閱項目 和刪除舊的訂閱這些訂閱方案能讓你 。 請參閱「訂閱用戶端以接收推播通知」 瞭解訂閱流程的詳細資訊

儲存新的訂閱資訊

  1. 如要預覽網站,請按下「查看應用程式」。然後按下 全螢幕 全螢幕
,瞭解如何調查及移除這項存取權。
  1. 按一下「應用程式」分頁中的「註冊 Service Worker」。在狀態方塊中 會看到類似以下的訊息:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. 在應用程式分頁中,按一下「訂閱推送」。你的瀏覽器或作業系統 詢問是否要允許網站傳送推播通知給你。按一下「允許」 (或其他項目) 您瀏覽器/OS 使用的對應語句)。狀態方塊中應會顯示類似訊息 改為:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
敬上
  1. 在 Glitch UI 中,按一下「View Source」,返回程式碼。
  2. 依序點選「Tools」和「Logs」,開啟 Glitch 記錄。個人中心 您應該會看到 /add-subscription,後面接著一些資料。/add-subscription 是 用戶端傳送 發布 要求訂閱推播通知時發出的要求。這些資料會用於 是您必須儲存的用戶端訂閱資訊。
  3. 開啟 server.js
  4. 使用下列程式碼更新 /add-subscription 路徑處理常式邏輯:
app.post('/add-subscription', (request, response) => {
  console.log('/add-subscription');
  console.log(request.body);
  console.log(`Subscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .push(request.body)
    .write();
  response.sendStatus(200);
});
敬上

刪除舊的訂閱資訊

  1. 返回「應用程式」分頁。
  2. 按一下「取消訂閱推送通知」
  3. 再次查看「毛刺記錄」。您應該會看到 /remove-subscription 追蹤 而非用戶端的訂閱資訊
  4. 使用下列程式碼更新 /remove-subscription 路徑處理常式邏輯:
app.post('/remove-subscription', (request, response) => {
  console.log('/remove-subscription');
  console.log(request.body);
  console.log(`Unsubscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .remove({endpoint: request.body.endpoint})
    .write();
  response.sendStatus(200);
});

傳送通知

如「傳送推送訊息」一節所述, 您的伺服器未實際傳送推送訊息給用戶端。 而是依賴推送服務來進行。基本上, 將訊息推送到客戶的流程 Service 要求 (網路推送通訊協定要求) 傳送至網路服務 (推送服務) 您為使用者所用的瀏覽器供應商所有。

  1. 使用下列程式碼更新 /notify-me 路徑處理常式邏輯:
app.post('/notify-me', (request, response) => {
  console.log('/notify-me');
  console.log(request.body);
  console.log(`Notifying ${request.body.endpoint}`);
  const subscription = 
      db.get('subscriptions').find({endpoint: request.body.endpoint}).value();
  sendNotifications([subscription]);
  response.sendStatus(200);
});
  1. 使用下列程式碼更新 sendNotifications() 函式:
function sendNotifications(subscriptions) {
  // TODO
  // Create the notification content.
  const notification = JSON.stringify({
    title: "Hello, Notifications!",
    options: {
      body: `ID: ${Math.floor(Math.random() * 100)}`
    }
  });
  // Customize how the push service should attempt to deliver the push message.
  // And provide authentication information.
  const options = {
    TTL: 10000,
    vapidDetails: vapidDetails
  };
  // Send a push message to each client specified in the subscriptions array.
  subscriptions.forEach(subscription => {
    const endpoint = subscription.endpoint;
    const id = endpoint.substr((endpoint.length - 8), endpoint.length);
    webpush.sendNotification(subscription, notification, options)
      .then(result => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Result: ${result.statusCode}`);
      })
      .catch(error => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Error: ${error} `);
      });
  });
}
  1. 使用下列程式碼更新 /notify-all 路徑處理常式邏輯:
app.post('/notify-all', (request, response) => {
  console.log('/notify-all');
  response.sendStatus(200);
  console.log('Notifying all subscribers');
  const subscriptions =
      db.get('subscriptions').cloneDeep().value();
  if (subscriptions.length > 0) {
    sendNotifications(subscriptions);
    response.sendStatus(200);
  } else {
    response.sendStatus(409);
  }
});
  1. 返回「應用程式」分頁。
  2. 按一下 [取消訂閱推送通知],然後再次點選 [訂閱推送]。 這不是必要動作,因為如先前所說,Glitch 會重新啟動專案。 每次編輯程式碼,並將專案設定為在啟動時刪除資料庫。
  3. 按一下「通知我」。您應該會收到推播通知。標題應該 為 Hello, Notifications!,而主體應為 ID: <ID>,其中 <ID> 是 隨機數字
  4. 請在其他瀏覽器或裝置上開啟您的應用程式,並嘗試訂閱推播通知 然後按一下「全部通知」按鈕。您應該在 您所有訂閱的裝置 (亦即推播通知內文中的 ID 是一樣的)。

後續步驟