用 Pusher 製作網站推播 Web Push 功能
Tags: javascript, pwa, tutorial, beginners
Published: 2022-10-18 12:30:43

## 本篇要解決的問題

今天看教學文的時候，看到一個名為 Pusher 的網站有提供網頁推播的功能，雖然大家都知道，網頁推播因為無止盡的「要求顯示通知」給玩壞了：

![萬惡的要求顯示通知視窗](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09xwo2kdgclqmldje6j7.png)

再加上實在是搞不懂 Safari 有沒有支援 Web Push 的功能，這幾年 Web Push 的相關文章也愈來愈少，但既然 Pusher 有免費的額度方案，就想說來試試看。

Pusher 安裝 Web Push 的步驟很簡單，基本上照著頁面說明的步驟，幾分鐘內就可以完成。

啊不過，所謂的簡單是針對 Windows 系統說的，遇到有著自己小宇宙的蘋果系統，因為 Pusher 上寫的步驟需要有一個付費的 Apple Developer 帳號，因此本篇就沒有實作讓 Safari 也能用 Web Push 的這部份。

本篇參考資源：
- [Build a Real-time Chat App with Pusher and Vue.js](https://www.sitepoint.com/pusher-vue-real-time-chat-app/)
- [Beams Web SDK Integration](https://pusher.com/docs/beams/getting-started/web/sdk-integration/)

---

## 建立 Pusher Beams App

進到 [Pusher](https://pusher.com/) 官網後，註冊會員並登入，註冊時的方案選擇免費的「Sandbox」就行，免費方案最高可以有 1000 個訂閱，詳細收費請見官網說明 [Pricing](https://pusher.com/beams/pricing)。

登入會員後進到後台，會看到二個選項：Channels、Beams。

Web Push 的功能是在 Beams 裡，因此點擊 Beams 中的 Get started：

![點擊 Beams Get started](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aefmd7aplsuz8b1mtpj.png)

Instance name 填上我們自己認得出是做什麼的名字就行：

![填寫 Instance name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqrfel67n5co3jzzjf1e.png)


要在哪裡使用 App 選擇 Web：

![選擇 Web](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bck5xb753yp32pce8x83.png)

接著，Pusher 讓人對他們的 UX 感到滿意的部份來了。

後續會看到 4 個步驟，說明文字都很清楚，就算英文不好，把程式碼複製貼上或按個 Download 什麼的也都做得到 XD。

4 個步驟寫在下面一段。

---

## 安裝 Pusher Web Push

### Step1 建立 SW.js

有看過一點 [PWA 的教學文](https://www.letswrite.tw/category/pwa/) 的話，會知道推播功能需要在網站有一個 Service Worker，簡稱 SW，由 SW 來處理接收 Web Push 等工作。

第一步很簡單，因為 Pusher 連下載檔案的按鈕都做好了，按下 Download 後，把下載下來的 service-worker.js 檔放進網站的根目錄就行。

要檢查有沒有放成功，只需要進到你的網站後，在網址後打上 service-worker.js，像這樣：

```html
https://www.xxxx.tw/service-worker.js
```

之後看頁面上有沒有出現一行：

```javascript
importScripts("https://js.pusher.com/beams/service-worker.js");
```

有出現就代表第一步成功，沒有出現或顯示 404 就要檢查是不是檔案傳錯地方。

這邊有一個地方 August 在文件上沒看到，就是有沒有可能不放在網站的根目錄下？因為曾經遇過只希望推播功能用在某個活動頁上的需求，如果是放在根目錄就是整個站都會用到。

### Step2 安裝 Pusher SDK

在要觸發讓使用者接受通知的頁面內，引用 Pusher 的 SDK 檔案，引用方式可以直接 CDN 的引用，或是 JS 內用 import。

直接用 CDN 的話就是頁面上加上一行：

```html
<script src="https://js.pusher.com/beams/1.0/push-notifications-cdn.js"></script>
```

import 的話方式如下：

```javascript
// 先安裝 package
$ npm install @pusher/push-notifications-web
// 或
$ yarn add @pusher/push-notifications-web

// 接著 JS 檔中 import
import * as PusherPushNotifications from "@pusher/push-notifications-web";
```

### Step3 要求顯示權限

第三步就是執行跟使用者要「顯示通知」的權限，就是那個大家都會按下「封鎖」的小方塊 XD。

這步也很簡單，因為 Pusher 都附上程式碼了，無腦的複製貼上就行，安裝 SDK 是用 CDN 的話，貼上以下：

```html
<script>
  const beamsClient = new PusherPushNotifications.Client({
    instanceId: '<YOUR_INSTANCE_ID_HERE>',
  });

  beamsClient.start()
    .then(() => beamsClient.addDeviceInterest('hello'))
    .then(() => console.log('Successfully registered and subscribed!'))
    .catch(console.error);
</script>
```

安裝 SDK 是用 import 的話，JS 中貼上以下：

```javascript
const beamsClient = new PusherPushNotifications.Client({
  instanceId: "<YOUR_INSTANCE_ID_HERE>",
});

beamsClient.start()
  .then(() => beamsClient.addDeviceInterest('hello'))
  .then(() => console.log('Successfully registered and subscribed!'))
  .catch(console.error);
```

這邊有 2 件事情要 **<u>特別注意</u>**，對，重要到都加上粗體跟底線了。

1. 這段程式碼麻煩包在一個按鈕點擊後的事件中，目的是讓使用者可以自行決定要不要允許推播。如果像上面官方給的範例直接執行的話，現在的使用者有 99.99999% 的機會會按下「封鎖」。
2. `addDeviceInterest` 這個很方便，簡單來說就是幫使用者做分組，上面的範例程式碼是把使用者分進「hello」這個群組，分組的目的就是，之後要推播時可以選擇分組推送，而不是無差別全部都推一波。至於怎麼分群就是各自網站的行銷需求來決定了。

因為是跟著官網練習，這邊就無腦的直接貼上程式碼，然後打開頁面，要求顯示通知的小方塊也按下「允許」，回到 Pusher 後台，就會看到左上角跳出一個通知，代表有接收到我們的允許：

![允許推播成功](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p90s8icylhdp66pvskdn.png)

繼續按下 Continue，到最後一步。

### Step4 發送一個推播 Web Push

最後一步就是用一個 POST 來實際發送一則推播，看到的說明會像這樣：

![Step4 發送一個推播 Web Push](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mbjmcf3igntqbkc8iqo.png)

裡面附上的程式碼會像是這個樣子：

```shell
curl -H "Content-Type: application/json" \
     -H "Authorization: Bearer EFF9531D9A8D41A483151DAD676D84997FF81229FC16E187E513ED8004B8D524" \
     -X POST "https://4104da6b-4575-49d7-b2a5-1192bc4799ad.pushnotifications.pusher.com/publish_api/v1/instances/4104da6b-4575-49d7-b2a5-1192bc4799ad/publishes" \
     -d '{"interests":["hello"],"web":{"notification":{"title":"Hello","body":"Hello, world!"}}}'
```

不用看這段寫的很長很可怕，簡單來說就是在終端機下命令，下什麼命令呢？下發送一個 POST 的命令，如果我們對調用 API 這件事情很熟的話，完全可以改用自己熟悉的 fetch、axios，或是可以再戰十年的 jQuery。

為了以後真的可以拿來當作是本站的推播訂閱功能，又怕忘記程式碼，August 這邊選擇用 [Postman](https://www.postman.com/) 來執行 POST，把這次的發送存下來，以後就可以直接改個參數使用。

Postman 是一個前後端的好幫手，直接用它們的操作介面就能 GET、POST 等來調用 API，August 在遇到新 API 時，很常先用 Postman 看看回應值會有什麼，就不用先花時間去寫幾行程式，而且還可以存下來，當作是 API 的文件。

Postman 相關的功能本站有寫過幾篇，還沒用過但有興趣的朋友們可以點來看：[Let's Write Postman](https://www.letswrite.tw/?s=postman)。

Pusher 第四步附上的命令，可以拆解成這樣：

- URL：https://xxx.pushnotifications.pusher.com/publish_api/v1/instances/xxx/publishes
- 參數：{ "interests": ["xxx"], "web": { ... } }
- Auth：Bearer xxx

打開 Postman 後，照著上面三個部份填上，會像這樣：

![填寫 URL、Bearer Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7b9vdx5rcmaune5nrnj.png)

![填寫參數](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwl8ksljj2zr7afqnyrq.png)

都填寫完後，最後按下 send，瀏覽器還打開的情況下，又是 Windows 電腦的情況下，就會看到通知啦~

![基本的通知樣式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxu97suf6vxk2pybi2ly.jpg)

如果發送後沒反應，可以檢查以下情況：

1. 是不是用 Mac 的電腦？Mac 不支援。
2. 網址是不是 https 開頭？Service Worker 只能在 https 內使用。
3. 如果不是 https，那網址是在開發狀態的 localhost 中嗎？

最後，所有可用的參數 [官方文件](https://pusher.com/docs/beams/reference/publish-payloads/#notification-object-format) 上有寫，整理如下：

```json
{
    "interests": ["群組名稱"],
    "web": {
        "notification": {
            "title": "標題",
            "body": "內文",
            "icon": "圖檔路徑",
            "deep_link": "連結"
        }
    }
}
```

如果都有填上值的話，看起來會像這樣：

![所有參數都有給值](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3st61c07shh24a5vpuy.jpg)

連結的部份如果想知道成效，一般會加上 utm 參數，然後從 GA 上看流量來源。

### 支援度

August 拿了幾個瀏覽器來測，結果是：

- Chrome：支援。
- Microsofe Edge：支援。
- Firefox：不支援。

Firefox 很神奇，雖然 Pusher 的文件上有說怎麼處理：[Web notification permissions in Firefox](https://pusher.com/docs/beams/guides/web-notification-permissions-in-firefox/)，但照著做了以後還是不行，看來，就是放生了。

Firefox 本身公告的這篇很有趣，講他們不想支援 Web Push 的原因：[Restricting Notification Permission Prompts in Firefox](https://blog.mozilla.org/futurereleases/2019/11/04/restricting-notification-permission-prompts-in-firefox/)，這還是 2019 年的公告了，又過了要 3 年，Pusher 的 Web Push 看來是不支援 Firefox 了。

如果有不死心想讓 Web Push 再次偉大的朋友，最後這邊附上 Safari 也能用的說明文件，因為必須要有付費的開發者帳號才行，August 就沒有實際測試了：[Safari configuration](https://pusher.com/docs/beams/getting-started/web/configure-safari/)。

---

## 未來本站會使用 Web Push

雖然網頁的 Web Push 在大家的努力之下被玩壞了，但知道了 Pusher 這個工具，免費方案又能有一千個訂閱，就想拿來用用，之後本站會加上一個「訂閱推播通知」的按鈕，按下允許通知後，就能接收到新文章的推播。

到時想訂閱新文章通知的朋友，記得只有 Windows 才支援喔，至於用 Macbook 的朋友…就拿去星巴克展示就好 XD~