いいからBlazorをさわるんだ

# はじめに

Blazorのプロジェクトの作り方やPWA(プログレッシブWebアプリケーション)化について、今年の秋辺りにいろいろやっていたのでまとめます。

この記事は[C#+WPFチューニング戦記](http://proprogrammer.hatenadiary.jp/) の最近の一部記事から多少情報を刷新したものです。

## 皆さんにBlazorをおすすめしている理由

ブラウザのプラグイン等を一切使わないSPA(シングルページアプリケーション)のメリットをそのままに、JavaScriptを1行も書かずにC#+HTMLでブラウザアプリケーションが作れるというのは、非常に良いと思いました。
PWA化するとC#のアプリケーションでありながら、C#のための.NET Framework/.NET Coreやアプリケーション自体のインストールすら不要です(PWA化するときは1行だけJavaScriptを書きますが、コピペです)。

# Blazorの紹介

BlazorとはMicrosoftのASP.NET Coreの一コンポーネントとして近年開発されているものです。
C#をブラウザ側で動かすことができるというものです。

## 開発場所とリリースの情報

オフィシャルのブログと開発場所です。

[Blazor 0.7.0 experimental release now available | ASP.NET Blog](https://blogs.msdn.microsoft.com/webdev/2018/11/15/blazor-0-7-0-experimental-release-now-available/)
https://github.com/aspnet/Blazor

## 何ができるのか

* サーバーサイドはテンプレートではASP.NET Coreを使います。
* クライアント側では.NET CoreのDLLをMono.wasmによってWebAssemblyにビルドして画面内で使うことができます(C#の言語的な便利機能はそのまま使用可能です。C#7.3で書いても大丈夫です)。さらにWebAssemblyと画面要素間を繋ぐための高度なフレームワークを構築してくれるので、JavaScriptのソースコードを触る必要は基本的にありません。
* HTMLとC#のClassの間でプロパティとDataBindingでき、HTML内にC#を埋め込むRazor構文を使用可能です。これらをクライアント側で実行できます。
* クライアント側の通信部がC#で記述できるので、JsonでやりとりするDTOをC#で一元管理できます。
* いわゆるSPAが基本構成となり、簡単にPWA化できます。

**要するに画面要素(HTML/CSS)以外、上から下までC#で書いてWebアプリケーションを作ることができるのです。**

# 動かしてみる

## 準備

1. .NET Core 2.1 SDK(2.1.500以降)をセットアップします。
2. ASP.NETとWeb開発ワークロードが選択されたVisual Studio 2017(15.9以降)を用意します。
3. Visual Studio Marketplaceからの最新のBlazor Language Services Extensions をセットアップします。
4. コマンドライン上でBlazorのテンプレートを構成します。

```
dotnet new -i Microsoft.AspNetCore.Blazor.Templates
```

## プロジェクトを立ち上げる

1. VisualStudio2017の新規プロジェクトで ASP.NET Core Webアプリケーションを選択します。
![NewProject.png](https://qiita-image-store.s3.amazonaws.com/0/62044/9540f81a-89b5-90e3-a257-f15004dca493.png)

2. Blazorのテンプレートを選択します。
![SelectTemplate.PNG](https://qiita-image-store.s3.amazonaws.com/0/62044/0d36c083-ac28-4cba-1955-6a98ac1fe581.png)

3. F5で実行して動くことを確認します。
![RunSPA.PNG](https://qiita-image-store.s3.amazonaws.com/0/62044/a30d3694-e103-91f3-1ab6-d772ac6fa309.png)


## PWA化

1.テンプレートで生成したプロジェクト *.Server に NuGet から WebEssentials.AspNetCore.PWA を追加します。
![Nugets.PNG](https://qiita-image-store.s3.amazonaws.com/0/62044/430ff103-0c82-b439-b31f-17fb4f441035.png)
2.Server側プロジェクトのStartup.csのConfigureServicesを以下のように書き換えます。

```c#
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddProgressiveWebApp(); // ←これを追加
    services.AddResponseCompression(options =>
    {
        options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
        {
            MediaTypeNames.Application.Octet,
            WasmMediaTypeNames.Application.Wasm,
        });
    });
}
```
3.Client側のプロジェクトの wwwroot に PWA に必要な manifest.json を追加します。
 
```json
{
  "name": "Progressive Web Apps",
  "short_name": "PWA",
  "description": "Creating PWA in ASP.NET Core.",
  "icons": [
    {
      "src": "/images/icon192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "/images/icon512x512.png",
      "sizes": "512x512"
    }
  ],
  "display": "standalone",
  "start_url": "/"
}
``` 
icons に記述したファイルが必ず実在するようにしてください。これを忘れてPWA化できずにハマる人がたまにいるそうです。

4.index.html を書き換えます。
serviceWorkerとmanifest.jsonの追加です。(残念ながらここで1行だけJavaScriptを記述します:sweat:)

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width">
    <title>BlazorPwaSample</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
    <link rel="manifest" href="/manifest.json" />
</head>
<body>
    <app>Loading...</app>

    <script src="_framework/blazor.webassembly.js"></script>
    <script>'serviceWorker' in navigator && navigator.serviceWorker.register('/serviceworker')</script>
</body>
</html>
```

5.httpsである必要があるので、Server側のプロジェクトでIIS Expressに以下の設定をします。
![IISExpressSetting.PNG](https://qiita-image-store.s3.amazonaws.com/0/62044/8156da3f-0b77-f226-4c86-cbd0a5c06923.png)
これを忘れてPWA化できずにハマる人がたまにいるそうです。

6.IIS Expressでデバッグ実行します。

7.Chromeで表示して以下のメニューがあることを確認します。
![menu.PNG](https://qiita-image-store.s3.amazonaws.com/0/62044/d08b9076-8abc-9c01-672a-06ae5d6c7f98.png)


PWA化するとDesktopにアイコンが表示されます。実行すると以下のような画面になります。
![PWA.PNG](https://qiita-image-store.s3.amazonaws.com/0/62044/42a2d2bb-a975-c4f4-6502-0b92be9b33b1.png)

# 機能を実装していく指針

* サーバーサイドの処理はServer側のプロジェクトに実装します。基本的には、表示に必要なデータを構成することのみをサーバー側の責務とします。
* レンダリング(HTML自体の構成)は主にクライアント側で行いますのでClient側のプロジェクトに機能を実装します。
* jsonで通信するクラスやサーバーとクライアントの両方で使用するユーティリティをSharedのプロジェクトに実装します。

## 汎用性が高いコントロールを作るために知っておくべきこと

以下のものを駆使して、汎用性に優れるコントロールを作成することができます。

* Parameter属性を用いたデータバインディング(Parameter属性は現時点では継承しないので、C#の継承でコントロールを作る際は注意が必要です)
* C#のパターンマッチングによるコントロールの挿げ替え(WPFにおけるDataTemplateのようなものを簡単に書けます)
* BlazorComponent を継承すると画面内のコントロールを作ることができます。また、Pages内のcshtmlは原則的にBlazorComponentを継承しています。
* C#のジェネリック(HTMLのページもジェネリックになります。汎用的なListBoxなどが簡単に書けます。)
* Blazorのカスケードパラメーター(WPFで言うところのinherit属性付きの添付プロパティのように、HTML上で外側の画面要素のプロパティを内側のプロパティのように使えます。スタイルやテーマなどを内側に伝えると非常に便利です。)

これらの情報に関する実践記事や動作するライブラリは、順次私のブログ上で展開していく予定です(ソースはGitHubに出します)。
[C#+WPFチューニング戦記](http://proprogrammer.hatenadiary.jp/) を時々覗いてみてください。

## おすすめの拡張

* Bootstrap 4を使うために BlazorStrap というものが存在します。
https://github.com/chanan/BlazorStrap


# 現在の状況

Blazorを取り巻く状況はまだ発展途上と言えます。

## まだ課題を抱えている部分

* C#コード上にブレークポイントを置く機能が動くようになったものの、デバッグに際して十全であるかはまだ心配です。
* .DLLをダウンロード(この部分はキャッシュ可能)して、それをMono.wasmがWebAssemblyにコンパイルして、そのあとにWebAssemblyとして動作します。このため少し、起動時間は長い印象があります(同等のものをJavaScriptで作って比較したわけではないので、現時点では感覚的な話です)。
* JavaScript <-> C# 間のマーシャリングはまだ使いやすくありません。
* 試験的実装であるため、まだプロダクトでは使わないほうが良いと考えます(Ver.1.0は来年でしょうか…)。

## 最近の動向

現在 Blazor 0.8.0 は Preview の状態です。

Blazor のうち Razor と呼ばれるHTML内にC#を混在させる部分が、最近 ASP.NET Core 3.0 にマージされました。
クライアントサイドの部分だけが現在 Blazor として開発継続しています。

# まとめ

C#で書いたコードがここまでしっかりクライアントサイドでHTMLと緊密に動くのは非常に気持ちが良いです。
来年、かなり手堅い形で正規リリースが期待できると考えています。
みなさんも一度触れてみてください。