PWAでプッシュ通知機能を爆速で実装してみた【OneSignal】

こんばんは。

**PWA Night Vol.31にて詳しく解説させて頂きました！**
発表資料もありますので詳しいそちらを参照してください。
ServiceWorkerの作り方やWebManifestの時短作成策など、PWA自体の実装面についても詳しく説明させていただきました！

https://ic731.net/docs/0915_PWA.html



前々回に引き続きPWA(Progressive Web App)並びにTWA(Trusted Web Activity)に関するお話です。
この前投稿した記事：[PWAを簡単にオフライン表示に対応させてみた](https://qiita.com/tomomi0115/items/0fb38333e8a0f00eb9ff)

さらにネイティブアプリに近づけるべく今回は**PWAでPUSH通知機能**を実装したいと思います。
※PWAで通知を受信できるのはWin/Mac/Androidのみです…iOSは知らん。

# 実装方法
今回はPWAの話もあるんですけど7割くらい(適当)はWebページ全体の話に毛が生えた程度なんでネットにたくさん書いてあるやつを使うだけです。
Webサイトから通知を送信する方法として以下の2つの手段があります。

- node.jsでで独自にPush通知を送信
- 外部サービス（俗に言うソフトウェア・アズ・ア・サービス）を利用して送信

今回**爆速で実装**をテーマとしているのでわざわざ独自で実装すると折角のPWAの長所である**インスタントさ**が薄れると思いますし、Node.jsを使わずに開発してる場合いちいちサーバー立ち上げてデーモン化して…っていう工程がめんどくさいand余計なリソースを要すると思います。
あと外部サービスを使うと優秀なアナリティクス機能が使えて、通知の反応率とかも調べられます。↓![rapture_20210312183931.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/26dd3552-3097-58d7-f5bc-c38a524596b5.png)



なので2つ目の外部サービスを使って実装していきたいと思います。（独自で実装しないのでcronとかを使って定期的に送信…とかはできなさそうです。まぁ時間指定は外部サービスでもできますけど。）

### プラットフォーム選び
プッシュ通知を提供している外部サービスを聞かれると大体

- **Firebase**のCloud Messaging
- **OneSignal**

の2つが思い浮かぶ人が多いと思います。（多分）

この2つから今回は**OneSignal**を選びます。
理由としては単純に**無料で使う際の制約が少ない**ってだけです。
どちらとも、無料で使うことができるんですけど**Firebaseだと通知に画像アイコンが使えない**というそこそこ致命傷級の制約があるんですけどOneSignalはそれがない。それが所以です…

ですがOneSignalにも制約があります。無料プランだと**10,000デバイス以上だと全員に送信されません。**まぁ個人開発レベルなら問題ないと思いますが。
![rapture_20210312173527.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/da12f644-6916-43ab-2920-3fc4d992ae4f.png)


もし300円とかのLiteプランでも出してくれれば使う気になるんですけどねぇ。従量課金ですから…
と愚痴ってもしょうがないんで早速やってみましょう。

# 実装
それではやりまっす。**PWAの雛形は[前々回の記事](https://qiita.com/tomomi0115/items/0fb38333e8a0f00eb9ff)を参考にしてください**。ここではそのページ「PWA Offline Test」を流用します。

## OneSignalの設定
まずはOneSignalのセットアップからやります。
Sign Upからアカウントを作ってください。
https://onesignal.com/
![rapture_20210312200234.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/c788134a-778a-07cb-86ac-16fca9d543f6.png)
登録したらNew App/Websiteから情報をいろいろ入力します。Choose Integrationのところは**Custom Code**を選んで、あとはサイト情報を入力してください。
![rapture_20210312171743.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/d3e19377-099c-ebdd-a2e9-e0d90816a7b3.png)
次に指示通り、**SDKファイルをサイトのルートディレクトリにアップロード**してください。
![rapture_20210312171734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/06860afb-031d-52de-8d55-13571897c775.png)
![rapture_20210312172758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/c5d5b2b1-f372-1b7e-7e45-2cae02ab38ac.png)
最後に表示されている以下のコードをhead直下にコピペします。これでOneSignal側での設定は以上です。
![rapture_20210312172925.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/792853e5-f151-825f-5d86-2c4a74d3232f.png)

## サイト側の設定
通常のWebサートで通知送信ならこれで終わりなんですけどこのままでは**PWAだとエラーが出る場合があります**。私の環境だとこの状況ではブラウザでは通知を受け取れるけどPWAアプリで受け取れませんでした。
別の方のQiitaの記事を参考にしました。
さっきダウンロードした2つのSDKファイルにServiceWorkerをインポートするらしいです。以下のようにファイルの内容を変更。

```js:OneSignalSDKUpdaterWorker.js
importScripts('serviceWorker.js');
importScripts('https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js');
```
```js:OneSignalSDKWorker.js
importScripts('serviceWorker.js');
importScripts('https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js');
```
これで送信する準備ができました。実際に送信してみましょう。

# 送信してみた。
## 通知を許可
デバイス上でサイト/PWAにアクセスすると画面右下にベルマーク(学校で集めるやつじゃない)があるのでそこをクリックすると**通知許可のダイアログが出ます**ので試しに許可。
![rapture_20210312173143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/0feedb15-2a90-0eea-89bd-162e3dedeaf0.png)
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/c661708e-bc94-ac7d-a583-5b9d55a891c5.png)

![Screenshot_20210312_204633.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/4205a7bb-0567-4269-3250-243cb5062e99.jpeg)

## 内容を作成
次にOneSignalのダッシュボードトップからNew Pushを選び内容を書きます。
![rapture_20210312173311.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/86a54b2f-43d9-4743-ac9e-3cdbcf78d322.png)
![rapture_20210312173323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/b8e51f1a-0f54-4b04-9e99-e57fb320e013.png)
タップしたときの動作や画像を表示するかなどの設定ができます。
内容を書いたらSend Messageで送信。これで通知を許可したデバイスに送信されるはずです。

## 確認。
### PCの場合
WindowsPCだとバッテリー残量とかが表示されると同様に通知が画面右端に表示されます。
![rapture_20210312173543.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/3f4b0eb8-889b-c37c-f6c5-fc03ef6a18ff.png)
Chromeで許可するとちゃんとPWA Offline Testも起動してくれました。
![rapture_20210312204225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/a194ac7d-5812-24a5-9bbf-c954263f0fcb.png)

### モバイル(Android)の場合
Androidの場合、ネイティブと全く同じで通知メニューの表示されます。
![Screenshot_20210312_204606.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/e5bb5e78-6529-aad6-7fcf-8c7028efbca7.jpeg)
また、画像は最大16:9のサイズだと全部表示されます。
![画像_2021-03-12_205107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/9e71af2b-2315-cf6e-d7e5-a8e3d3fc19c4.png)

※デバイスでの通知ON/OFF等のの管理は右下のベルマークから設定できます。
![Screenshot_20210312_204654.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/95b5cb4b-9595-81b4-0011-b023f5c8c4a1.jpeg)

##ハマったところ
Operaだけ何故か通知が表示されなくて、どうしたんかな～と思ったら開発者メニューのコンソールでERR_BLOCKED_BY_ADBLOCKERっていう読み込みエラーが。
![rapture_20210312173213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/4f7d437c-62cf-6604-311e-045d1826b72e.png)
いろいろ試したところどうやらOperaの**トラッカー防止機能**が悪さをしてるみたい。解除したら受信されました。（別に広告ブロッカーつけてると通知来ないわけではありません）
![スクリーンショット 2021-03-12 173159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/41c1f195-98dc-7823-e983-47600bedcbb3.png)

ざっと爆速で通知機能の実装の仕方を説明してみました。
ぜひご参考にしてみてください。より一層ネイティブアプリに近づいたと思います。