Blazor PWAテンプレートを使って、以前作成した電卓アプリを再作成する

今回は以前作成した[「Blazorで、電卓アプリをつくってみる」](https://qiita.com/kimuradesu/items/1f96d3833f096eed4b3a)を最新のBlazor　PWAテンプレートで、再作成してみたいと思います:writing_hand:

#PWA概要
PWAとは「Progressive Web Apps」のことで、Webアプリケーションをあたかも独立したアプリケーションとして実行(表示)できるプログラムのことです。以前[「Blazorで、電卓アプリをつくってみる」](https://qiita.com/kimuradesu/items/1f96d3833f096eed4b3a)というタイトルで、実際に様々なデバイスにインストールして使用することができる電卓を作成しました。この当時は、BlazorのデフォルトテンプレートではPWAを作成することはできず、独自に仕組みを組み込むものでした。しかし、最近のプロジェクトテンプレートであれば、PWAを作成することができるので、最近のテンプレートに沿って電卓アプリをPWA化してみたいと思います。

https://qiita.com/kimuradesu/items/1f96d3833f096eed4b3a

#実装

##新規プロジェクトの作成
PWAに対応したBlazorアプリケーションを作成するには、Blazorプロジェクトの新規作成時に、**「プログレッシブ Web アプリケーション(P)」**にチェックを入れて作成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/2357e88c-32ca-5ef9-2a9b-9a7b50f6d5d7.png" width=90%>

##プロジェクトファイルの構成
PWA対応を行うには下記を満たす必要があります。

+ サイトのHTTPS化
+ アイコン(favicon)の設置
+ manifest.jsonの作成
+ ServiceWorkerの作成

そのためPWAテンプレートで作成されたプロジェクト構成では、`manifest.json`や`service-worker.js`など上記を満たすファイルが作成されます。

![pwa2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/7b9d7c5b-ace6-abfa-f4fd-c2d71a965ec1.png)

##電卓アプリの移植
電卓アプリを実現するコンポート(Index.razor)は、以前作成したコードがそのまま動きます。PWA対応にとって重要なのは`index.html`や`manifest.json`、`service-worker.js`などのファイルです。以前は`service-worker.js`に、オフライン実行の為のフェッチファイルを全て列挙したり、`manifest.json`にfaviconの定義を行いました。何か間違ってるとブラウザがPWAとして認識せず苦労した覚えたがあります。PWAテンプレートでは最初からこれらのファイルが用意されている為、導入しやすくなっています。

#実行
この状態で実行してみましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/53c1d5a0-c27a-9c09-4a3b-056448d53575.jpeg" width=50%>

ちゃんと「インストールしますか？」も表示されますね。これで、標準のテンプレートだけでPWA化へ対応できることがわかりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/48d2b3d2-6bfc-3f35-a4e0-636f8ea0b952.jpeg" width=50%>

インストールされたアプリケーションを実行すると、あたかも独立したアプリケーションを実行している様に振る舞う事が可能になっています:ok_woman:

#オフライン実行
PWAの特徴として、[サービスワーカー（Service Worker）](https://developers.google.com/web/fundamentals/primers/service-workers?hl=ja)という仕組みを使って、Webサーバーとの通信が切断されてもキャッシュされたファイルによりプログラムを実行することができます。キャッシュの機能は、初回のローディング時間を大幅に削減することができる為、実用的な機能です。キャッシュを有効にさせるには、`servfice-worker.js`内に記述されたフェッチするファイルパスを書き込むことで有効になります。

しかし、BlaozrのPWAテンプレートで作成される`service-worker.js`を見てみると、`開発中はキャッシュさせるなよ！コード変更してもキャッシュされてるから反映しないぜ！`とコメントされています。キャッシュされてしまうと、ブラウザのキャッシュクリアを実行しないと反映されない為の注意ですね。その為、実際にオフライン実行で使用される`service-worker.js`は別に定義されています。

```javascript:service-worker.js
// In development, always fetch from the network and do not enable offline support.
// This is because caching would make development more difficult (changes would not
// be reflected on the first load after each change).
self.addEventListener('fetch', () => { });
```

#デプロイ用のService Worker
PWAテンプレートでは **発行**した時のみ使用されるデプロイ用の`service-worker.published.js`が用意されています。発行を使ってデプロイした環境では、このServiceWorkerによって、初回のローディング時にすべてのファイルがフェッチされます。尚、この動作は規定で行われます。多数のイメージファイルなどのコンテンツを含める場合、すべてのファイルを取り込もうとする為、注意が必要です。

このあたりの動作については、[公式のドキュメント](https://docs.microsoft.com/ja-jp/aspnet/core/blazor/progressive-web-app?view=aspnetcore-6.0&tabs=visual-studio#caveats-for-offline-pwas)に詳細が記述されています。

https://docs.microsoft.com/ja-jp/aspnet/core/blazor/progressive-web-app?view=aspnetcore-6.0&tabs=visual-studio#caveats-for-offline-pwas

うーん、このドキュメントを見ると、オフライン実行は必ずしも必要ないし、複雑だよ！と、書かれてますね:sweat:今の時代、ネットに接続されないデバイスは少ないしオフライン実行環境は用途が限定されるのかもしれません:grimacing:

#Webサーバーにデプロイしてみる
実際に、Webサーバーにデプロイしてみましょう。Webサーバーにデプロイされたアプリケーションをインストールすると、ネットワークを切断してもアプリを実行することができます:slight_smile:

[**デモ**](https://blazorpwa-417a8.web.app/)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/75fbe5ba-4d79-9bd1-7224-8643718b5c5b.jpeg" width=30%>

#おわりに

Blazor PWAテンプレートを使用したPWAアプリケーションの作成方法についてご紹介しました。PWAテンプレートを使うことでBlazorアプリケーションを簡単にPWAへ対応させることが可能となっています。一方で、Blazorを取り巻く環境については[.Net MAUI](https://docs.microsoft.com/ja-jp/dotnet/maui/what-is-maui)の登場によって、ネイティブ寄りなアプリの開発が可能になってきており、Webブラウザの範疇以上のことができないPWAの存在は薄まった印象があります。しかし、年々各ブラウザのHTML5/CSS実装状況は進んでおり、Webブラウザができることが広がっています。 [12/20の @jsakamoto さんのアドベントカレンダー Blazor WebAssembly で作った Web アプリ "snow catch" ゲームを、🎮 ゲームパッド (ジョイスティック) で操作できるようにする](https://qiita.com/jsakamoto/items/4705be2e5c6c7f1fccc8)にも書かれていますが、Webブラウザが各種デバイスにアクセスできるようになってきていますし、クライアント側でランタイムなどのインストールが必要のないPWAは大きな可能性を含んでいるのではないでしょうか:zap::zap::zap::rocket::rocket::rocket: