@angular/pwaとpush通知について

# はじめに

今だにAngularPWA関連でポチポチいいね貰うのでアップデート記事を書いておきます。

- @angular/pwaについて
- push通知について

# @angular/pwaについて

## Angular6で投入された`ng add`の話

AngularCLIは`schematics`というコード生成ツールを用いてcomponentやserviceの生成をしてくれます。`ng generate component hoge`とかですね。v6で追加された`ng add`では、そのschematicsを用いてnpm packageのインストールからNgModuleなどへのコード追加をやってくれます。

## @angular/pwaは`ng add`専用のコード生成補助パッケージです

### 何をやってくれるのか

`npm i @angular/service-worker`を肩代わりして、さらにconfigファイルやngModuleのコード追加してくれるものです。注意点としては、`@angular/pwa`はふつうに`npm i @angular/pwa`しても意味ないやつです。schematicsで動かさないといけないからです。よってこれを使えるかどうかは以下のように分かれます。

- AngularCLIを採用している既存PJ
  - `ng add @angular/pwa`しましょう
- これから新規で起こす場合
  - `ng new app`してから`ng add @angular/pwa`しましょう
- AngularCLIを採用していない既存PJ
  - 大人しく`npm i @angular/service-worker`してセットアップしましょう。その時も`@angular/pwa`がやっていることを参考にすると良いと思います。

以下[公式ドキュメント](https://angular.jp/guide/service-worker-getting-started)から`@angular/pwa`がやっていることの引用です。

> 1. `@angular/service-worker`パッケージをプロジェクトに追加します。
2. CLIでService Workerのビルドサポートを有効にします。
3. アプリケーションモジュールにService Workerをインポートして登録します。
4. index.htmlファイルを更新します。
  - manifest.jsonファイルを追加するためのリンクを含めます。
  - theme=colorのメタタグを追加します。
5. インストール可能なプログレッシブウェブアプリ（PWA）をサポートするアイコンファイルをインストールします。
6. ngsw-config.jsonというService Worker構成ファイルを作成します。このファイルは、キャッシュの動作やその他の設定を指定します。

### インストール方法

二重に書いても意味ないのでこちらの記事などをご参照ください。ほぼ自動化されて手前どもがやることはほんと無くなりました。`manifest.json`や`ngsw-config.json`は適時調整しましょう。ngsw-configのキャッシュ制御は大変深く腕の振るいどころです。（[参考記事](https://qiita.com/studioTeaTwo/items/74219721ca51f6ffeabd)）

[Angular CLI v7でPWAを作ってみよう！]
https://qiita.com/puku0x/items/a6db78cc67d1eb960384

# push通知について

## swPushがあるよという話

公式ドキュメントで相変わらず取り上げられていないので存在感が薄いですが、昔からいます。
疑心暗鬼な方は[こちらのソースコード](https://github.com/angular/angular/blob/master/packages/service-worker/src/push.ts)を確認してください。ほら、いるでしょう！

ソースコメント見てる限りはexperimentalという訳でもありません。
ドキュメントに無いのは、iPhoneがアレな状況なので盛り上がらないのとか、他の件ではサーバ用意してデモできるようにコンテンツ構成しているけどpush通知は色々記事作るのめんどいぞというあたりかもしれませんが、全て憶測です。

公式以外の参考情報ではこちらが大変有用です。完成度が高く私が申し上げることはありません。

[Angular Push Notifications: a Complete Step-by-Step Guide]
https://blog.angular-university.io/angular-push-notifications/

## Angularでpush通知を実装する

と、流石にそれで終わってはアレなので、簡単にサマリをまとめておきます。基本的にpush通知はその名の通りサーバプッシュなのでサーバ、そしてブラウザにお任せです。@angular/service-workerでpushAPIの購読も良しなにしてくれるので、フロントエンドでは購読許可のUI作り込みが戦場となります。

swPushでは以下の機能を提供しています。

```typescript
class SwPush {
  messages: Observable<object>
  notificationClicks: Observable<{...}
  subscription: Observable<PushSubscription | null>
  isEnabled: boolean
  requestSubscription(options: { serverPublicKey: string; }): Promise<PushSubscription>
  unsubscribe(): Promise<void>
}
```

- pushイベントの購読登録/解除 `requestSubscription/unsubscribe `
  - ユーザーに購読許可を出しYESを頂く際に使うやつです。横着してロードイベントに任せずにアプリケーションのUXを熟考して購読許可のタイミングを練りましょう。
- メッセージのObservableプロパティ `messages`
  - ただブラウザのネイティブ通知UIに出すだけならsubscribeして放っておけばいいが、このObservableがpushサービスで取得した通知群を流してくれるのでオリジナルUIを作れます。
  - 例えばアプリケーション内部の専用通知タブに出すとかの用途です。
  - この場合、サーバからpushされた通知内容にクライアントでデータ加工したり付与できます。
- 通知をクリックした時の該当メッセージとアクションの取得 `notificationClicks`
  - どんなリアクションするか、腕の振るいどころです。

## ブラウザのネイティブ通知UIを使わずにオリジナルUIを作る

push通知というとブラウザが用意しているネイティブUIしか思い浮かばなかったですが、`messages`プロパティのユースケースはこちらの記事が大変参考になりました。twitterの通知タブのような作り込みをpush通知を利用して作っています。

[A new Angular Service Worker — creating automatic progressive web apps. Part 2: practice]
https://medium.com/google-developer-experts/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-2-practice-3221471269a1

ただ、これやるならiPhoneまで考えるとwebSocketで作るという話あります。それでも技術的に関心あるとか、iOSにpushAPIが実装された未来から当記事にやって来られた方は、こちらのgifでおおよそ雰囲気がつかめると思います。

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/194428/bcbb2ea9-8b4f-fca1-aa29-5fa9230f10ee.gif)

実装コードも記事内のリンクからいけます。`message: Observable`をsubscribeして、あとはふつうにアウトプットしたいUIにセットしているだけです。

## 早くiOSにpushAPIが実装されますように。

以上です。