サンプルコードで学ぶPWA

# はじめに

Google I/O 2017の動画を確認し、そろそろPWAについて真面目に把握していかなければと思い至り、GitHubからいくつかサンプルプログラムを探してきて触ってみたので基本的な技術情報と合わせてまとめました。なのでPWA初心者向けです。

特定のJSフレームワークを扱う専門のエンジニアでない限り（私自身がそうなので）、それぞれのJSフレームワークの対応状況なども気になるところだと思いますので、 `React.js` , `Angular` , `Vue.js` の3つにおけるPWAのサンプルについても調べました。

確認した手順などを含めて要点だけまとめていますが、詳細はそれぞれのGitHubページを参照しつつcloneして触ってみて頂ければと思います。


# シンプル構成

まずはJSフレームワークなどが入っていないシンプルな構成で、PWAの仕組みについてざっくりまとめました。

## [PWA retrofit](https://github.com/sitepoint-editors/pwa-retrofit)

余計なものが入っていないのでPWAの仕組みを把握するのに適したサンプルという印象。
cloneした後、何もせずともそのまま実行可能。

```
$ npm start
```

デフォルトでは `http://localhost:8888/` にアクセスするとサンプル画面が表示される。

![スクリーンショット 2017-06-02 0.05.36.png](https://qiita-image-store.s3.amazonaws.com/0/3324/af6bd75d-7cc1-6196-01fa-ccc214a425d2.png)

### 主な構成

```
├── favicon.ico
├── （省略）
├── images
│   ├── （省略）
│   └── workbench.jpg
├── index.html
├── js
│   ├── main.js (Service Workerをインストールしているプログラム）
│   └── offlinepage.js
├── manifest.json　 (Web App Manifestファイル)
├── offline
│   └── index.html
└── service-worker.js (Service Workerファイル)

```

### Web App Manifest

アプリの情報を記述する。ホーム画面に追加する際のアイコンなどの情報もこのマニフェストファイルの定義に従う。記述方法などの詳細はMDNの [Web App Manifest](https://developer.mozilla.org/ja/docs/Web/Manifest) を参照。

なお、`manifest.json` のファイル名はなんでも良いがアプリを構成するhtmlの `<head>` にマニフェストファイルへのリンクを記述しておく必要がある。

```html
<link rel="manifest" href="/manifest.json">
```

### Service Workers

PWAの動作を担う実行環境としてインストールされるファイル。以下のように存在チェックして `register` することでインストールされバックグラウンドでJSを動作させることができる。なお、これもファイル名はなんでも良い。処理的にトップページから最初に呼ばれるJSファイルの冒頭でこの記述をしておくのが定石。とにかくService Workerとして認識させ、インストールしてもらうだけが目的ならファイルの中身は空でも良い。

```js:main.js
// enable service worker
if ('serviceWorker' in navigator) {
  // register service worker
  navigator.serviceWorker.register('/service-worker.js');

  // 省略
}
```

Service Workerはネットワークリクエストを横取りしてレスポンスを返したり、Push通知を受け取ってNotificationを表示することができる。これによってService Workerが事前にインストールされていれば、オフラインでも画面を表示したり、ページを開いていなくても通知を受け取って通知バーにNotificationを表示することができる。オフライン表示のためにあらかじめ画像などのファイルをキャッシュさせるのもService Workerで行う。

#### 参考

- [超詳解！Service Worker Deep Dive ── HTML5 Conference 2016セッションレポート](https://html5experts.jp/horo/21360/)
- [
Introduction to Service Worker（英語）](https://developers.google.com/web/ilt/pwa/introduction-to-service-worker)
- [W3Cの仕様（英語）](https://w3c.github.io/ServiceWorker/)

# React.js

## [react-pwa](https://github.com/paulhoughton/react-pwa)

> Simple progressive web app starter kit

と書いてある通り、React.jsを使ったPWAの最小構成。そのままでは「Home Page」とだけ書かれたテンプレート画面が表示されるだけとなっている。

```
$ npm run build
$ npm start
```

デフォルトでは `http://localhost:3000/` で動作。

![スクリーンショット 2017-05-28 17.20.34.png](https://qiita-image-store.s3.amazonaws.com/0/3324/4140ec77-584f-ac21-ef91-981bbea3ce39.png)

最小構成とはいえ、 `webpack` ベースでテストなどの各種ツールも使う前提となっており、モダンなフロントエンド開発に必要なものはきちんと詰め込まれている印象。またServiceWorkerも、 そのまま実装するのではなく `webpack` 向けの [offline-plugin](https://github.com/NekR/offline-plugin) を使う方式になっており、実用的なテンプレートになっている。

ちなみに、同じ作者がReact.jsのサブセットである [Preact](https://github.com/developit/preact) を使った同様のサンプルも公開している。

### [preact-pwa](https://github.com/paulhoughton/preact-pwa)

> Material Design Progressive Web App Preact starter kit 

と書いてある通り、マテリアルデザインにも対応している模様。ただしそのまま実行しても見た目はreact-pwaと同じテンプレート画面でマテリアル感は無かったのでスクリーンショットは割愛。


## [react-pwa-reference](https://github.com/localnerve/react-pwa-reference)

[Express](http://expressjs.com/ja/), [Fluxible](https://github.com/yahoo/fluxible) などのトレンド技術をひとしきり詰め込んである印象。サンプルとしてパッケージ化されて開発に使う `npm` タスクも一覧にまとまっているので、軽く触ってみる範囲で困ることはない。ひとまず以下で試すことができる。

```
$ npm install
$ npm run dev
```

デフォルトは `http://localhost:3000/` で動作。

![スクリーンショット 2017-05-28 17.02.55.png](https://qiita-image-store.s3.amazonaws.com/0/3324/fef47b61-99f0-b7b7-f3e9-68f972798b67.png)

公式によると使っているものは以下のような感じ。

> Node
> Express
> React (Facebook)
> Fluxible (Yahoo)
> sw-toolbox, sw-precache (Google)
> babel6, gulp4, webpack, eslint, mocha/chai, sass

ServiceWorker周りは [sw-toolbox](https://googlechrome.github.io/sw-toolbox/) , [sw-precache](https://github.com/GoogleChrome/sw-precache/) を使っている。これらはGoogleが公開している [Service Worker Libraries](https://developers.google.com/web/tools/service-worker-libraries/?hl=ja) のライブラリである。

このほかテストツールなども含めてひとしきりのツールがぎっしりつまっていて初心者は見ただけで圧倒されるが、デモ画面を見るとわかるようにサンプルの完成度が高いので、これらのツール類を使ったアプリの完成形はイメージしやすい。

### 参考 

[Fluxible + React の概要をまとめた](http://qiita.com/srd7/items/85e89f16b1b390170579)
[GoogleChrome/sw-precache が便利そう](http://lealog.hateblo.jp/entry/2017/01/05/211650)

# Angular

## [Progressive Hacker News client built with Angular](https://github.com/housseindjirdeh/angular2-hn)

[Progressive Hacker News](https://angular2-hn.firebaseapp.com/) のサイトをAngular2でPWA化している。

```
$ npm install
$ npm start
```

デフォルトは `http://localhost:4200/` で動作。

![スクリーンショット 2017-05-29 0.50.24.png](https://qiita-image-store.s3.amazonaws.com/0/3324/eadb66f0-673f-fbb2-3132-989b59d6da77.png)

ServiceWorkerは [sw-toolbox](https://googlechrome.github.io/sw-toolbox/) , [sw-precache](https://github.com/GoogleChrome/sw-precache/) を使っている。一応レスポンシブをうたっていて、デスクトップも合わせて扱う場合のPWAの事例としても参考になるかもしれない（サンプル上は見た目はあまり変わらない）。

## [NG-Pokedex](https://github.com/coryrylan/ng-pokedex)

Angular2 でPWA化されたポケモン図鑑。 `angular-cli` を使う方式のため、まずはインストールが必要。

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

あとはコマンド1つでひとまず動作する。

```
$ ng serve
```

デフォルトは `http://localhost:4200/` で動作。

![スクリーンショット 2017-05-30 0.45.49.png](https://qiita-image-store.s3.amazonaws.com/0/3324/5fa83df8-02d0-6a71-590b-746ab6bbc64f.png)

ServiceWorkerは [Workbox](https://workboxjs.org/) を使っている。また、通知周りは [firebase](https://firebase.google.com/) にデプロイする仕組みも含まれている。


### 参考

[Fast Offline Angular Apps with Service Workers](https://coryrylan.com/blog/fast-offline-angular-apps-with-service-workers)

## 補足

AngularはAngular CLI と Angular Mobile ToolKit などのツール類もPWAをサポートする前提で充実してきている印象。ただし4系以降ではもっと力を入れるとも言われているのでまだまだ動きがありそう。

[Angular最新トピックとテクニックをng-japan代表のlacoさんに聞いてきた！（後編）](https://html5experts.jp/shumpei-shiraishi/22923/)

# Vue.js

## [Vue Simple PWA](https://github.com/BosNaufal/vue-simple-pwa)

> Simple Progressive Web App Example Built With Vue.js.

Vue.jsで作られたシンプル構成のPWA。[デモページ](https://bosnaufal.github.io/react-simple-pwa) も公開されている。

```
$ npm install
$ npm run dev
```

`http://localhost:8080/` で動作する。

![スクリーンショット 2017-05-30 23.21.45.png](https://qiita-image-store.s3.amazonaws.com/0/3324/05971630-bed7-5319-9988-0f57a84850c4.png)

ServiceWorkerまわりは Cach APIで未実装部分だったAPIを補うための [cache-ployfill](https://github.com/dominiccooney/cache-polyfill) が含まれているなどやや古い実装の印象（Chrome46以降はこれは不要）。

### 参考

[Service Worker の紹介](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers?hl=ja)
[Chrome 46 に Cache.addAll() を実装した](http://blog.nhiroki.jp/2015/09/02/cache-storage-addall)


## [vue-pwa-boilerplate](https://github.com/vuejs-templates/pwa)

Google I/O 2017の[Production Progressive Web Apps With JavaScript Frameworks ](https://www.youtube.com/watch?v=aCMbSyngXB4) のセッションで紹介された Vue.jsでPWAを作るためのテンプレート。

`vue-cli` を使うため未インストールの場合はまず `npm install` しておく

```
$ npm install -g vue-cli@latest
```

`git clone` してきたテンプレート（ここでは `pwa` ）を使って `vue-cli` でプロジェクトを作成する。

```
$ vue init pwa my-project
```

作成したプロジェクトをビルドして実行する

```
$ cd my-project
$ npm install
$ npm run dev
```

実行すると自動でブラウザが起動し `http://localhost:8080/` を呼び出す。

![スクリーンショット 2017-05-31 0.04.49.png](https://qiita-image-store.s3.amazonaws.com/0/3324/313e5438-645f-d251-3990-fe064668a641.png)

ServiceWorkerは前出の [sw-precache](https://github.com/GoogleChrome/sw-precache/#wrappers-and-starter-kits) のWebPack向けラッパーである [sw-precache-webpack-plugin](https://www.npmjs.com/package/sw-precache-webpack-plugin) を使って実装している。また、Vue.jsのプロジェクトを構成する（テスティングフレームワークなども含む）標準的な要素一式が揃っていおり、テンプレートながらキャプチャのようにサンプル用の画面も実装されているので、これからVue.jsを使ってPWAを作りたい場合は周辺のライブラリの使い方も含めて完成形がイメージしやすい。


# まとめ

PWAの仕組みを実装レベルで把握しようと思ってGitHub上のサンプルプログラムを巡ってみました。が、JSフレームワークでの実装例を調べ始めると、移り変わりの激しいモダンなフロントエンド系技術を色々目の当たりにすることになり、（私のようにこの領域の専門ではないエンジニアにとっては）思った以上に把握に時間を要しました。とはいえ、実際に導入するとなるとReact.jsにするかAngularにするかといった所から検討したり、 [Service Worker Libraries](https://developers.google.com/web/tools/service-worker-libraries/?hl=ja) などの活用を検討すると思いますで、これらのサンプルの存在はその助けになると思います。変化が激しいだけにサンプルは多数ありますが、便利なCLIやnpmなどでパッケージ化された仕組みは充実しています。ローカルで動かしてみるだけならコマンドを数回叩くだけだったりするので、非常に良い時代だなと思いました。

Angularではつい先日バージョン4.2がリリースされたのに合わせて [公式サイト](https://mag.osdn.jp/17/06/15/163000) 自体がServiceWorkerを活用してPWA対応しているようです。このようにPWAの動向的には今後も色々動きがありそうですが、現時点では各フレームワークが対応できておりライブラリもこなれているので、PWAを導入するうえで大きな障壁は無いと思われます。ただ、PWAを含めた周辺のフロントエンド開発自体がまだ技術的に過渡期で今後も様々な変化が起こると考えられるため、現時点でどのような選択をしたとしても今後も変化に追従していく覚悟は必要だと思われます。