Cordova Angular6のアプリをPWA化してみる

今更ですが、Angular6 + OnsenUIを使って作ったシンプルなCordovaのAndroidアプリをPWA化してみた時のメモです。もともとRESTなどWebトランザクションは使っていませんので簡単に動くはずという目論見です。CordovaのPluginを一部使っていますが、以下のようなコードで切り分けて、Pluginなしでも動くようにしておきました。

    declare var cordova: any;
       ...
       if (cordova) {
           ....
      }

# ChromeにLighthouseをインストール
[https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=j](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja)から「Chromeに追加」ボタンをクリック。

Chromeの右上に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/2649373d-b165-8c40-8fc4-bae649443354.png)
灯台アイコンが現れたらクリック→「Options」でProgressisve Web Appのみを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/0b956470-9886-cff1-84f7-d67a2e862a92.png)

# 既存のプロジェクト名を確認
`angular.json`を開いてプロジェクト名を確認

    ...
      },
      "defaultProject": "mycordova"
    }

# @angular/pwaをインストール
アプリのルートフォルダで`ng --version`でほかのモジュールのバージョンを確認。

```
Angular CLI: 6.0.8
Node: 8.12.0
OS: win32 x64
Angular: 6.1.7
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.8
@angular-devkit/build-angular     0.6.8
@angular-devkit/build-optimizer   0.6.8
@angular-devkit/core              0.6.8
@angular-devkit/schematics        0.6.8
@angular/cli                      6.0.8
@angular/platform-server          6.1.10
@ngtools/webpack                  6.0.8
@schematics/angular               0.6.8
@schematics/update                0.6.8
rxjs                              6.3.2
typescript                        2.7.2
webpack                           4.8.3
```

@angular-devkit/architectなどと同じバージョン番号の0.6.8をセレクト。
この選択が良いのか自身がないですが、少なくともバージョン指定なしで最新の@angular/pwaでは動作しないようでした。先ほど確認したProject名を指定。

    ng add @angular/pwa@0.6.8 --project mycordova

````
Installed packages for tooling via npm.
CREATE ngsw-config.json (392 bytes)
CREATE src/assets/icons/icon-128x128.png (1253 bytes)
CREATE src/assets/icons/icon-144x144.png (1394 bytes)
CREATE src/assets/icons/icon-152x152.png (1427 bytes)
CREATE src/assets/icons/icon-192x192.png (1790 bytes)
CREATE src/assets/icons/icon-384x384.png (3557 bytes)
CREATE src/assets/icons/icon-512x512.png (5008 bytes)
CREATE src/assets/icons/icon-72x72.png (792 bytes)
CREATE src/assets/icons/icon-96x96.png (958 bytes)
CREATE src/manifest.json (1073 bytes)
UPDATE angular.json (4732 bytes)
UPDATE package.json (2999 bytes)
UPDATE src/app/app.module.ts (4356 bytes)
UPDATE src/index.html (1065 bytes)
````
いろいろとファイルを準備してくれる。

# app.moduel.tsの確認
src/app/app.module.tsの内容を確認。

以下がでたらめなところに突っ込まれてコードが破壊されていたので、適切な場所に移動。

````src/app/app.module.ts
    import { ServiceWorkerModule } from '@angular/service-worker';
    import { environment } from '../environments/environment';
````

さらに以下を追加。

````src/app/app.module.ts
@NgModule({
  ...
  imports: [
    ...
    ServiceWorkerModule.register('/ngsw-worker.js', { enabled:  environment.production })
  ],
````

# src/index.htmlを確認
こちらは以下が追加されていたけど特に問題なし。
````src/index.html
  ...
  <link rel="manifest" href="manifest.json">
  <meta name="theme-color" content="#1976d2">
  ...
````

#キャッシュを設定
OnsenUIやCordovaアプリが使用しているリソースをキャッシュする設定に修正。

````ngsw-config.json
{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js",
        "/*.eot",
        "/*.svg",
        "/*.ttf",
        "/*.woff",
        "/*.woff2",
        "/images/**"
      ]
    }
  }, {
````

# Lighthouseで状態を確認
ここで`ng build --prod`でビルドしてApacheサーバからChromeで表示。その後、Lighthouseでレポート作成。なお、`ng build --watch`ではPWA関連のファイルが準備されないみたい。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/c3954e93-4890-5a29-a2ab-c552e2b270c1.png)

これらを順番に解決していく。

# Does not redirect HTTP traffic to HTTPS の修正
apacheのhttpd.confの最後に以下のmod_rewriteのHTTPからHTTPSへのリダイレクト設定を追加。

````httpd.conf
# HTTPをHTTPSにリダイレクトする設定。
<ifModule mod_rewrite.c>
      RewriteEngine On
      LogLevel alert rewrite:trace3
      RewriteCond %{HTTPS} off
      RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</ifModule>
````

# Does not provide fallback content when JavaScript is not available の修正

````src/index.html
<body>
  <noscript>
    Please enable JavaScript to run this application.
  </noscript>
````
noscriptを追加。

# Does not provide a valid apple-touch-iconの修正

````src/index.html
  <link rel="apple-touch-icon" href="assets/icons/icon-192x192.png" />
````
アイコンへのリンクを追加。

# Page load is not fast enough on mobile networksの修正

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/0a071d2e-73fe-6a57-4355-b2775b71a797.png)

遅いって言われても。。。アプリにはあまり改良の余地はない。。。

LighthouseのPerformanceを有効にして調査をお願いしてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/4748fcbe-6163-2fce-3d36-d020f7024223.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/22aa821f-ea5d-ec8a-387a-51acca72f688.png)

Enable text compressionが主要因だそうで、Apacheでテキスト圧縮を有効にしてみる。

````httpd.conf
LoadModule deflate_module modules/mod_deflate.so
LoadModule filter_module modules/mod_filter.so
````
上記モジュールを有効に。

[Apacheのmod_deflateでデータを圧縮して転送量を削減する](https://oxynotes.com/?p=6519)
を参考にさせていただきます。

````httpd.conf
<IfModule mod_deflate.c>
     SetOutputFilter DEFLATE
     BrowserMatch ^Mozilla/4\.0[678] no-gzip
     BrowserMatch ^Mozilla/4 gzip-only-text/html

     BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
     SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary
     SetEnvIfNoCase Request_URI _\.utxt$ no-gzip
 
     AddOutputFilterByType DEFLATE text/plain
     AddOutputFilterByType DEFLATE text/html
     AddOutputFilterByType DEFLATE text/xml
     AddOutputFilterByType DEFLATE text/css
     AddOutputFilterByType DEFLATE application/xhtml+xml
     AddOutputFilterByType DEFLATE application/xml
     AddOutputFilterByType DEFLATE application/rss+xml
     AddOutputFilterByType DEFLATE application/atom_xml
     AddOutputFilterByType DEFLATE application/javascript
     AddOutputFilterByType DEFLATE application/x-javascript
     AddOutputFilterByType DEFLATE application/x-httpd-php
</IfModule>
````

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423554/90f4073c-fcee-ac7b-789d-ab7c57df43b9.png)

何とか合格をいただきました。
ちなみにServiceWorkerなどを含むこの状態で再びCordovaをビルドしても問題なく動作するようです。

# 参考ページ
[Building A PWA Using Angular 6](https://www.smashingmagazine.com/2018/09/pwa-angular-6/)
[はじめてのプログレッシブウェブアプリ](https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/?hl=ja)
[apacheでhttpへのアクセスをhttpsへ自動リダイレクトする](https://qiita.com/sue71/items/100004b704b9ff129b09)
[Apacheのmod_deflateでデータを圧縮して転送量を削減する](https://oxynotes.com/?p=6519)
[Apacheの使用方法](https://so-zou.jp/web-app/tech/server/apache/settings/gzip.htm)