Push通知やってみたい!!!
けどkotlinもswiftも書けないしな〜
ブラウザにしてもwebsocket?なにそれ食えるの
インフラエンジニアの自分には厳しいかな
...
等思ってたらなんとservice workerというものを使えば簡単にブラウザで試せるという噂をキャッチ
しかもcreate-react-app(cra)でテンプレを作ればservice workerのボイラープレートもくっついてくるっぽいのでこれを使うことにしました
なお筆者はフロントエンドに造詣が全くないですので意味・単語等間違いがありましたらご指摘ください。
環境
- linux
- chromium(72.0.3626.119)
- firefox dev edition(66.0b12)
成果物
step by step
登場人物
- フロントエンド(react)
- バックエンド(適当なwebサーバー)
- pushサービス(firefoxならmozilla, chromiumならgoogleになります)
いつもの依存モジュールのインストール
カタカタしていると安心するのでtypescriptにてお送りします
eslintはcraに入っています(最新版入れるとyarn start
時に怒られます)
yarn create create-react-app pj --typescript
cd pj
yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser @typescript-eslint/typescript-estree esli
nt-config-prettier eslint-plugin-prettier eslint-plugin-react husky lint-staged
ServiceWorkerの登録
そのままだとprecacheしかやってくれませんので、通知を受信できるように編集します
src/serviceWorker.ts
に3点追記します
-
applicationServerPublicKey
- web-push使って生成しておきます
-
urlB64ToUint8Array
- base64をuint8arrayに変換するヘルパー関数です
-
https://github.com/GoogleChromeLabs/web-push-codelab/blob/master/app/scripts/main.js#L31
を参考にts化します
-
registration.pushManager.subscribe({})...
- pushManagerにsubscribe情報を登録します
- pushサービスからエンドポイント情報が返ってくるのでそれをバックエンドに通知します
- この際、デフォルトのままだと型定義がが無いと怒られるのでtsconfig.jsonのlibに
webworker
を追記します
ServiceWorkerの有効化
デフォルトではserviceworkerのregisterが切られてますので有効化します
src/index.tsx
のserviceWorker.unregister()
をserviceWorker.register()
に変更します
こいつを有効にしてもproductionなenvじゃないと動きません(reactのdocumentにもbuildして試してみてねと書いてあります)
通知ボタンの配置
App.tsx
にコンポーネントを配置します。イメージとしてはポチると通知が飛ぶ感じですね
デバッグ時にめんどくさいのでservice workerのunregisterボタンも用意しておきます
swの差し替え
このままでもserviceworkerは動きますが、デフォルトのwebpack.config.jsはworkboxのGenerateSWによってserviceworkerを生成しているため、precache機能しか発揮してくれません
というわけで自作のswに差し替えちゃいましょう
react-app-rewiredの追加
yarn eject
を行って出てきたwebpack.config.jsを書き換えても良いですが不可逆的変化怖い...
故にcraのconfigを上書きできるreact-app-rewired
を使います
yarn add -D react-app-rewired
config-overrides.js
に書いていきます
自作service workerを書く
本当はtypescriptで書きたかったけど、webpack力がないので断念
バックエンドを書く
otiai10さんの記事を参考に実装しました
やったことはtypescript化したことくらいなので省略します
動かす
yarn build && serve -s build
oO(なぜかchromiumはアイコンが変わらない・・・)
所感
- serviceworkerをtypescriptで書けなかったの悔しい!!!
- serviceworker自体はドキュメントが充実している事もあってさくっと作れた
- 微妙にchromimとfirefoxで挙動が違った(エラーとか)のに苦労した(chromiumの方がエラー多かった印象)
- ブラウザのdevtoolというのを初めて触ったが、以下の点でchromiumの方が使いやすかった
- Javascript contextを指定できる(例えばsw.jsにするとselfがServiceWorkerGlobalScopeになる)
- Service Workerのunregisterをdevtoolで行える(firefoxは
about:serviceworkers
)- 当初この記事に従って
about:debugging#workers
を使用したが、なぜかこのページを開いているだけでCPU負荷が高騰してFirefox全体がフリーズするまでになってしまった- warningにも書かれていたが、multiple content processesとの併用が原因なのかもしれない
- 当初この記事に従って
- pushサービスのendpointのurlが短い(気持ちの問題)
- フロントエンドすごい(特にエコシステム)
その他備忘
- serviceworkerはhttps経由もしくは通知元がlocalhostの場合のみ有効になる
- typescriptでservice-workerを書く時はひと工夫必要