5行でわかるプッシュ通知【VAPID】

HTMLとサービスワーカーしかない[簡易なサイト](https://github30.github.io/web-push-study/)を作りました。
ここに通知機能を実装してみてください😸

https://github30.github.io/web-push-study/

ソース
https://github.com/GitHub30/web-push-study

まず、[サイト](https://github30.github.io/web-push-study/)を開いてコンソールを出しましょう。

Chrome ( Ctrl + Shift + J )
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/6e482967-d8d9-db0d-2c4c-556a34961b2e.png)

Firefox ( Ctrl + Shift + K )
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/46cec9c9-034b-d6de-fb08-645ce1527f8e.png)

:::note alert
`allow pasting` と表示された場合は、allow pastingとキーボードで入力してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/16086204-fb54-71ba-81bc-8f996ab559e7.png)
:::

[Android](https://developer.chrome.com/docs/devtools/remote-debugging/)、[Microsoft Edge](https://blogs.windows.com/msedgedev/2016/05/16/web-notifications-microsoft-edge/)、[Safari](https://developer.apple.com/videos/play/wwdc2022/10098/)でも試せます。

コンソールにコードを入力し、Enterキーで実行していきましょう。

# 1行目 通知の許可をもらう

```javascript
await Notification.requestPermission()
```
左上から`許可する`をクリックしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/528007ff-f7c0-a474-fae5-b01a1b7a4e80.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/86d76679-1572-4cef-39d5-4e46698078b3.png)


# 2行目 サービスワーカーを登録する

```javascript
navigator.serviceWorker.register('./service-worker.js')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/2da74367-04fa-06d8-551d-09bdc28ece3f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/9335fc55-1652-10af-7855-3085c144dfe7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/b6dff405-f1a5-efdd-18a0-bd29c893d84c.png)


# 3行目 鍵を準備する

```javascript
var applicationServerKey = 'BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaNndIo'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/35bab092-6758-e34e-a146-49ec1a9a475e.png)

<details><summary>鍵を作成する場合</summary>

```javascript
var vapidDetails = await fetch('https://web-push-server.vercel.app/api/generateKeys').then(r=>r.json())
```
Node.js、Python、OpenSSLで作ることもできます。
https://github.com/web-push-libs/web-push#generatevapidkeys
https://gist.github.com/cjies/cc014d55976db80f610cd94ccb2ab21e
https://github.com/zivver/web-push/blob/master/README.md#using-openssl
</details>

# 4行目 サブスクをもらう

```javascript
var subscription = (await (await navigator.serviceWorker.ready).pushManager.subscribe({ userVisibleOnly: true, applicationServerKey })).toJSON()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/d10beb89-a270-46ca-b322-75dd7245340e.png)
`applicationServerKey`に公開鍵を設定します。

<details><summary>鍵を作成した場合</summary>

```javascript
var subscription = (await (await navigator.serviceWorker.ready).pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: vapidDetails.publicKey })).toJSON()
```
</details>


# 5行目 プッシュ通知を送る

```javascript
fetch('https://web-push-server.vercel.app/api/send', {
  method: 'POST',
  body: JSON.stringify({ subscription, payload: { title: 'やあ😸' } })
})
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/a26f1e39-8b46-980b-9c56-7824468aeb37.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/13c4e9db-46fc-3620-315e-84824194d460.png)


<details><summary>鍵を作成した場合</summary>

```javascript
fetch('https://web-push-server.vercel.app/api/send', {
  method: 'POST',
  body: JSON.stringify({ vapidDetails, subscription, payload: { title: 'やあ😸' } })
})
```
作成した鍵を送ります。
</details>

Node.jsやPythonで簡単に送ることもできます。
https://github.com/web-push-libs/web-push
https://github.com/web-push-libs/pywebpush

### curlで送る
```javascript
copy(`curl https://web-push-server.vercel.app/api/send -d '${JSON.stringify({ subscription, payload: { title: 'やあ😸' } })}'`)
```

<details><summary>鍵を作成した場合</summary>

```javascript
copy(`curl https://web-push-server.vercel.app/api/send -d '${JSON.stringify({ vapidDetails, subscription, payload: { title: 'やあ😸' } })}'`)
```
作成した鍵を送ります。
</details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/d67c6ebc-d675-4fa3-bb52-d5653198ddc6.png)
`Network`タブの`send`上でコピーすることもできます。Windowsの方はPowerShellでもよいです。

https://curlconverter.com/

PythonやPHPに変換も可能です。

### クリック時のリンクを設定する

```javascript
fetch('https://web-push-server.vercel.app/api/send', {
  method: 'POST',
  body: JSON.stringify({
    subscription,
    payload: { title: 'Open Yahoo!', data: { url: 'https://www.yahoo.co.jp/' } }
  })
})
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/85831176-36a7-8b7d-c4cc-9862c657b9d1.png)


### アクションボタンを作る

アクションを作ることもできます。

```javascript
fetch('https://web-push-server.vercel.app/api/send', {
  method: 'POST',
  body: JSON.stringify({
    subscription,
    payload: {
      title: 'やあ😸',
      body: 'どこに行きますか？🍉',
      actions: [
        { title: 'visit Google', action: 'https://google.co.jp/' },
        { title: 'visit Mozilla', action: 'https://www.mozilla.org/' }
      ]
    }
  })
})
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/fb597915-1a81-ce97-ab71-b9c2dd82b4c8.png)

アイコン、優先度、振動、音を変更することもできます。

https://developer.mozilla.org/ja/docs/Web/API/ServiceWorkerRegistration/showNotification

# 追記

上記手順をデモにしました。参考になれば幸いです。

https://github30.github.io/web-push-demo/

ソース
https://github.com/GitHub30/web-push-demo

# 参考

https://web-push-server.vercel.app の実装
https://github.com/GitHub30/web-push-server