Angular CLI 1.6 で PWA を作ってみよう！

この記事は[Angular Advent Calendar 2017](https://qiita.com/advent-calendar/2017/angular)の22日目の記事です。

##※ 注意 ※
記事の情報が古くなっています。

Angular CLI 6.0.0以降をお使いの場合は「[Angular CLI v6でPWAを作ってみよう！](https://qiita.com/puku0x/items/a6db78cc67d1eb960384)」を参照してください。

##はじめに
![image.png](https://qiita-image-store.s3.amazonaws.com/0/106886/22ccf80e-eecc-1322-cc06-8ad8a09a92fa.png)

[Angular CLI](https://cli.angular.io/)は今や[Angular](https://angular.io/)を使ったSPA開発には欠かすことのできないものです。

Angular CLI 最新版では、
- Service Worker
- Universal (SSR)
- App Shell
がサポートされているのでPWA[^1]を作るのも簡単になりました。

早速やってみましょう:grinning:

[^1]: Googleが提唱する[Progressive Web Apps](https://developers.google.com/web/progressive-web-apps/)の略。Webアプリにネイティブアプリ並のUXを提供する。

## 1. Angular CLIのインストール
Angular CLIをインストールしましょう。
※ 執筆時点では 1.6.1 が最新

```
$ npm install -g @angular/cli
```

## 2. 新規アプリ作成

`ng new`で新しいアプリを作ります。

```
$ ng new my-app --routing --service-worker
```

`--service-worker`オプションを付けると自動でService Workerが組み込まれます。

## 3. `@angular/platform-server`のインストール

アプリが生成されたディレクトリに移動して、

```
$ cd my-app
```

npmで`@angular/platform-server`をインストールします。

```
$ npm install @angular/platform-server --save
```

## 4. Universal用のファイル生成

Angular CLI 1.6からSchematicsにUniversalが追加されました。

```
$ ng generate universal my-universal-app
```

これだけでUniversal用のファイル生成と`.angular-cli.json`の設定をやってくれます。
[以前](https://github.com/angular/angular-cli/wiki/stories-universal-rendering)と比較すると非常に簡単になりましたね！

## 5. App Shellの生成
[App Shell](https://developers.google.com/web/fundamentals/architecture/app-shell)はUIが機能するために必要な最小限のHTML/CSS/JavaScriptです。アプリのロード中に表示するプレースホルダーとして利用することで、アプリが起動するまでの体感スピードを上げることができます。

下記のコマンドで生成可能です。

```
$ ng generate app-shell shell --universal-app=my-universal-app
```

パスはデフォルトで`/shell`となりますが、`--route`オプションで変更可能です。

```shell:パスを変更する場合
$ ng generate app-shell shell --universal-app=my-universal-app --route=my-path 
```

## 6. もうちょっとPWAっぽくする

このままでも良いのですが、`manifest.json`が無かったりApp Shellが空っぽだったりするのでちょっとイマイチですね...:sweat_smile:

https://github.com/puku0x/angular-pwa-sample を参考に

- manifest.json 追加
- ランチャー用アイコン 追加

と手を加えてみましょう。

この他、アプリの見た目が気になる場合は

- [Angular Material](https://material.angular.io/) 追加
- App Shellにプログレスバー 追加

などすると良いと思います。

「とりあえず動作確認したいだけ」という場合は省略してOKです。

## 7. ビルド

いつもと同じようにビルドします。特別なことはしません。

```
$ ng build --prod
```

## 8. ブラウザで表示

アプリをブラウザで表示してみましょう。

```
$ npx pushstate-server ./dist
```

サーバ起動後、ブラウザで`localhost:9000`を開くと表示されます。

## 9. 比較

何もしていないときと比べて表示速度がどれだけ改善されたか見てみましょう（[ここ](https://puku0x.github.io/angular-pwa-sample)からプレビューできます）。Chromeの開発者ツール等で回線速度を3Gに設定すると比較しやすくなると思います。

PWA化前は↓こんな感じです。 [[ソース](https://github.com/puku0x/angular-pwa-sample/tree/old)]

<img width="983" alt="PWA化前" src="https://qiita-image-store.s3.amazonaws.com/0/106886/d9c568a5-9a06-f168-2c14-a8f1fa993468.png">

ツールバーが表示される（First Paint）まで約2000msといったところでしょうか。

App Shellを組み込むと、

<img width="983" alt="PWA化後" src="https://qiita-image-store.s3.amazonaws.com/0/106886/9f500397-05fb-16c0-c7e4-b9ff4a0fe4c0.png">

約1500msに短縮されます。

さらに、Service Workerが登録されキャッシュが有効になると、

<img width="983" alt="PWA化後（Service Workerキャッシュ有効）" src="https://qiita-image-store.s3.amazonaws.com/0/106886/44bf6e24-fcd2-34ac-2512-58080b38a8c2.png">

アイコンが表示される（First Meaningful Paint）まで含めて約500msになります。

かなり高速化できましたね :raised_hands:

## まとめ

最新のAngular CLIではPWA実装が非常に簡単になりました。

2017年はPWA元年らしいので、皆さんもこれを機にPWAデビューしてみましょう:muscle: まだ間に合います！

`@angular/service-worker`については今回はキャッシュ用途のみでしたが、アプリの更新監視やプッシュ通知などもあるので今後活用していきたいところです。

今回のサンプルは[ここ](https://github.com/puku0x/angular-pwa-sample)からダウンロードできます。

明日は[ic_lifewood](https://qiita.com/ic_lifewood)さんです！

## 参考URL
https://blog.angular.io/angular-5-1-more-now-available-27d372f5eb4e
https://blog.angular-university.io/angular-app-shell/