[Rails] Lighthouseで PWAスコア100点をとるためにやったこと 

## 目的
[Google Lighthouse]( https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk) PWAスコアで100点とる

## やったこと
* 対応前の把握 → PWA 56点 :cry:
* 対応 :muscle:
* 対応後のチェック → PWA 100点 :relaxed:

---

# (宣伝） PWA対応したサイトの紹介
* [dokode](https://www.dokode.work/)
   * 個人で作成している研究者向けイベント紹介サイトです！
   * ![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/479fe829-707f-b6ac-67e9-91eebe0d4a3f.png)

* アプリ環境
    * Rails 5.2
    * Bootstrap 4
    * Heroku (Hobby plan)
    * Postgresql 10.0

このアプリをPWA対応してゆきます

---

# 対応前の把握 :cry:
* [Google Lighthouse]( https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk)でチェックします
* Progressive Web App は 56/100点 です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/7cfec278-dc38-62f3-b4fc-ffbd8a5c5df4.png)


---

# 対応 :muscle:
* [Google Lighthouse]( https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk)からの指摘
  1.  Does not respond with a 200 when offline.
  *  User will not be prompted to install the Web App.
  *  Does not redirect HTTP traffic to HTTPS
  *  Does not register a service worker
  *  Is not configured for a custom splash screen.
*  対応方針
    * 1, 4 → (1) Serviceworkerを導入し、offline時キャッシュされたオフライン画面を表示させて対応
    * 2, 5 → (2) manifest.jsonを適切に導入して対応
    * 3 → (3) HTTPS対応

---

# (1)-1 Serviceworkerを導入 !
RailsでServiceworker簡単に導入するために、[gem serviceworker-rails](https://github.com/rossta/serviceworker-rails)を使いました。

## gemをインスト-ル
下記をGemfileに追加して `bundle install` を実行します。

```Gemfile
gem 'serviceworker-rails'
```
## rails generate
下記のrails generateコマンドを実行します。

```console
rails g serviceworker:install
```
## generateされたファイルの説明
ファイルが4つ作成されます。

* `app/assets/javascripts/serviceworker.js.erb` - Serviceworkerのキャッシュの設定
* `app/assets/javascripts/serviceworker-companion.js` - Serviceworker読み込むためのファイル
* `public/offline.html` - serviceworker.js.erbを通してブラウザにキャッシュされて、ネットワークオフライン時表示されるhtml。
* `app/assets/javascripts/manifest.json.erb` - web app manifest

## 作成されたファイルの編集
* キャッシュされたoffline pageの設定はすでにされています。

servicewoker 完了 !

---

# (1)-2 Serviceworkerが動いているか確認
* Chromer Dev toolで offlineにして、リロードしてください。
* offline.htmlが表示されていれば、Serviceworkerが無事導入されています！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/fbcf682f-9c2c-b456-fb6a-8256fdb208e1.png)

---

# (2)-1 manifest.jsonを導入
次にmanifest.jsonを導入します。
既に、serviceworker-railsを導入したときインストールされた。manifestファイルを適切に使うだけです。 

##　`app/assets/javascripts/manifest.json.erb` を編集します。

```app/assets/javascripts/manifest.json.erb
<% icon_sizes = Rails.configuration.serviceworker.icon_sizes %>
{
  "name": "Dokode App", # アプリ名
  "short_name": "Dokode", # 短い名前 12文字以内
  "start_url": "/",
  "icons": [
  <% icon_sizes.map { |s| "#{s}x#{s}" }.each.with_index do |dim, i| %>
    {
      "src": "<%= asset_path "serviceworker-rails/icon-#{dim}.png" %>", # アイコンファイル作成して保存する（後述）
      "sizes": "<%= dim %>",
      "type": "image/png"
    }<%= i == (icon_sizes.length - 1) ? '' : ',' %>
  <% end %>
  ],
  "theme_color": "#ffffff",
  "background_color": "#FFFFFF", # スプラッシュスクリーンの背景色
  "display": "fullscreen",
  "orientation": "portrait"
}

```

## アイコンファイル用意
serviceworker-railsは icon sizeは `%w[36 48 60 72 76 96 120 152 180 192 512]` と[定義されています](https://github.com/rossta/serviceworker-rails/blob/4ebe4fff21f96775dc3ff62129ec10de4f2cc991/lib/serviceworker/engine.rb#L13) 。
これらすべてのサイズのファイルを用意して、 `app/assets/images/serviceworker-rails` にコピーします。

* （参考までにですが、アイコンは [App Icon Resizer](https://resizeappicon.com/) を使って作成しまいました:wink:。）
   ![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/9e825bfd-fd87-676d-da01-84107edeceb6.png)
* assets/images/serviceworker-rails配下に配置しました。
   ![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/52bfe085-d64b-417d-0459-4dcfabb76fb4.png)

manifest.json 完了!

---

# (2)-2 manifest.jsonが動いているか確認
* Androidでlocalhost.jsonにアクセスして ホーム画面に追加して、アイコンが表示去ればOK

![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/2708996a-fff7-6407-7d05-9f34841e76dd.png)

---

# (3) HTTPS 対応
下記3点おこないました

* Server
    * Herokuのhobby planはHTTPS対応なのでserverの対応は不要
* HTTPからHTTPSへのリダイレクトの設定

```config/environments/production.rb
  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  config.force_ssl = true # これを追加
```

* httpを使っているリソースをhttpsへ変更する
    * サムネイルの作成を wordpressの API `http://s.wordpress.com/mshots/v1` を使って動的に行っていた。
これを、事前にサムネイルを作成してS3に保存してhttpsで取得するように変更（ 関連拙記事. [Herokuのrailsアプリでheadless chromeを使ってwebページのスクリーンショットをとる](https://qiita.com/junara/items/375c4b18486cb4fd2a43) ）

HTTPS対応完了 !

--- 

# 対応後チェック :relaxed:

---
# Lighthouse PWAスコア 100点 !
![image.png](https://qiita-image-store.s3.amazonaws.com/0/124445/1b8479b0-a036-ad7a-0db6-9e7d0ca1cc00.png)

---
# chromeでもPWAと見なされてアプリのインストールも促される ！
![image.gif](https://media.giphy.com/media/3EiNW26GljjeO71Q38/giphy.gif)
![Screenshot_20180807-091907_Photos.jpg](https://qiita-image-store.s3.amazonaws.com/0/124445/0eb9ccf1-efc2-89ca-1c9b-916c3c940f2c.jpeg)

---
# まとめ
* PWAの対応するならまずLighthouseでチェック！
* Railsで PWA check listのservice worker項目に対応するだけならserviceworker-railsで楽ちん
* PWA対応すれば、chromeで「にゅっと」でて、アプリっぽくなります！

---
# 参考
* [Google Progressie Web Apps](https://developers.google.com/web/progressive-web-apps/?hl=ja)
* [Google Progressive Web App Check List](https://developers.google.com/web/progressive-web-apps/checklist?hl=ja)