Blazor のコンポーネントをパッケージ化して再利用する

# (架空のシナリオ)

とある Blazor アプリケーションの開発にて、「流れる文字」を実装する要件が発生したため、早速、"Marquee.razor" というコンポーネントとして実装しました。
※註: これはネタです。普通はこういうもの作るときは [CSS アニメーションで作って下さい](https://qiita.com/nissuk/items/7d5545a9f6177ff965dc)。
![fig000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/c40dce6c-6089-2312-afa7-d8627db6a43a.png)

これで、任意の .razor ファイル中で `<Marquee />` とマークアップすることで、

```html:*.razor
<Marquee Text="Hello, World!" />
```
流れる文字を実装できました!

![movie-001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/2b576e37-a13c-75c1-3884-533d2720b023.gif)

※註: 繰り返しますがこれはネタです。普通はこういうもの作るときは [CSS アニメーションで作って下さい](https://qiita.com/nissuk/items/7d5545a9f6177ff965dc)。

# 他のプロジェクトでも使いたい (再利用したい) !

さてこのように作成した Blazor コンポーネント、**他のプロジェクトでも使いたくなる**ことがあるでしょう。

そのようなときはどうするか?

もちろん、`.razor` ファイルを、会社のファイルサーバに置いておいて、「皆さん、コレ使ってくださーい」として、各自コピーして使うようなこともできます。

しかし、`.razor` ファイルだけではなく、その Blazor コンポーネントの動作のための補助用途の `.cs` C# ソースファイルも必要だったりしたらどうしましょうか?
「`.razor` ファイルを自分のプロジェクトにコピーしたんですけど、コンパイルできませーん」
「あー、`xxx.cs` ファイルもコピーしてー」
とするのでしょうか。

この程度ならまだしも、さらに `.css` ファイルなども必要な Blazor コンポーネントとか、どんどん、必要なファイルが増えたらどうしましょう。

はたまた、ファイル数の心配はない場合でも、バージョン管理や新バージョンへの更新はどうしましょうか。

「すみませーん、ファイルサーバの `.razor` ファイルを直接、リンク参照してたのですが、今朝ビルドしたらコケたんですが」
「あー、すんません、古いメソッド削除して上書き更新してましたー」

とかどうしましょう。

...ということで、ソースコードを生のまま共有フォルダに置くようなことはやめまして、**再利用したい Blazor コンポーネントは、"NuGet パッケージ" (拡張子 .nupkg) 化しましょう!**

大丈夫、手持ちの Blazor コンポーネントのコードを NuGet パッケージ化するのは、簡単ですよ!

# まずはクラスライブラリ化する

まずは、再利用したいコンポーネントを、独立したプロジェクトに切り出してください。

ということで新規に .NET Core プロジェクトを作成します。
プロジェクトの種類として、"Razor クラスライブラリ" というのを作ればよいです。

## dotnet CLI の場合

`dotnet new` コマンドを使い、作成するプロジェクトの種類名として "razorclasslib" を指定します。

特にそれ以上指定がない場合は、カレントフォルダ名をプロジェクト名としてプロジェクトファイル一式が生成されます。

ここでは、カレントフォルダの下に、"MarqueeLib" というサブフォルダ (= プロジェクト名にもなる) を `-o` スイッチで指定してプロジェクト作成する例を示します。

```shell
> dotnet new razorclasslib -o MarqueeLib
```

## Visual Studio の場合

プロジェクトの新規作成ダイアログを開きましょう。
そして "Razor クラスライブラリ" を選んで次へ進みます。
![fig0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/ca6c51c7-a84c-1f98-ead4-529f486df8a5.png)

プロジェクト名を入力して先へ進みます。
![fig0-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/d01ef310-ae20-0dd3-2fa8-ad50696628ef.png)

使用する ASP.NET Core のバージョンなどを指定します。
なお、本日時点では、Visual Studio 2019 Preview (v.16.4 Preview 6) で作業中、ASP.NET Core の "3.1" を選ぶと、正しくプロジェクトが作成できませんでした (ので、ASP.NET Core "3.0" を選択して先へ進めました)。
![fig0-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/0a1444e3-4624-e2ca-c7ab-39388854aebb.png)

Razor クラスライブラリのプロジェクトとして "MarqueeLib" ができあがります。
見ると、最初からサンプルコードがいくつか既に入っています。
今回ライブラリ化したいのは、別途既に作成済みの "Marquee.razor" であるとわかってますので、バッサリこれら最初からあるファイルは削除してしまいます。
![fig0-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/fae37ccd-68e5-9fed-896c-228a185cd1c4.png)

## ここからは dotnet CLI でも Vsiaul Studio でも同じ作業

不要ファイルを削除しましたら、先ほどアプリケーション開発中に作成した "Marquee.razor" を、こちらのクラスライブラリのプロジェクトのフォルダに（普通にエクスプローラやシェルを用いたファイル操作で）移動します。
![fig0-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/06d6400a-210b-d137-b20f-eb056ca49684.png)

以上で、再利用したい Blazor コンポーネントを、独立したクラスライブラリプロジェクトに切り出すことができました。

ここまでの作業は、"NuGet パッケージ化" に特化した作業ではなく、**ごくごく普通の C# プログラミング**な内容ですね。

# パッケージ化する

さてさて、いよいよ NuGet パッケージ化します!

とはいっても、ソースコードをパッケージ化するために書き換えとか、そういった編集作業は要りません。

**単純に、「このクラスライブラリプロジェクトについて、NuGet パッケージファイルを生成してください」というコマンドを発行するだけ**です!

## dotnet CLI の場合

カレントフォルダがプロジェクトファイル (.csproj) があるフォルダである状態で、`dotnet pack` を実行することで、そのカレントフォルダ内にあるプロジェクトファイル (.csproj) を元に、NuGet パッケージファイルが生成されます。

通常は最適化された Release ビルドでパッケージ化し配布すると思いますので、`-c` スイッチを付けて、"Release" 構成でビルド、パッケージするのがよいでしょう。

```shell
> dotnet pack -c:Release
```

これだけです!

以上の操作で、プロジェクトファイルがあるフォルダの下、`./bin/Release` フォルダに `MarqueeLib.1.0.0.nupkg` ファイルができあがります。

![fig0-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/a9cd80c4-1547-f81e-b4f2-faa14db280a0.png)

## Visual Studio の場合

通常は最適化された Release ビルドでパッケージ化し配布すると思いますので、ビルド構成を "Release" に切り替えておきます。

その上で、ソリューションエクスプローラからプロジェクトを右クリックし、出てきたメニューから「パック」を選択すると、ビルドが始まって、最終的に NuGet パッケージが生成されます。
![fig0-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/f5bd2888-24b7-8e73-bbff-7f54fba0b1af.png)

これだけです!

以上の操作で、プロジェクトファイルがあるフォルダの下、`./bin/Release` フォルダに `MarqueeLib.1.0.0.nupkg` ファイルができあがります。

# 再利用の方法

こうしてできあがった NuGet パッケージファイル (.nupkg) を利用者皆で共有することとなります。

後述しますが、NuGet パッケージ化された Blazor コンポーネントを利用する側は、**NuGet パッケージ名を指定した "パッケージ参照" をプロジェクトに追加するだけ**で、**その Blazor コンポーネントを利用可能**となるのです!

さてさて、では、作成した NuGet パッケージファイルを、どこに置いておけば良いのでしょうか?

例えば、インターネット上の nuget.org に発行すれば、世界中に向けて配布することができます。

また、会社内でのみ使いたい場合は、利用者から参照可能な、**ファイルサーバ上の共有フォルダに置いておくだけでも OK** です!

NuGet パッケージファイルの共有・配布にはいろんな手段・方法があります。
下記 URL なども参考になるでしょう。

- [独自の NuGet フィードをホスティングする | Microsoft Docs](https://docs.microsoft.com/ja-jp/nuget/hosting-packages/overview)

今回は、「.nupkg ファイルをファイルサーバ上の共有フォルダに置いて共有・再利用する」場合について、以下に詳しく説明してみます。

## 開発環境に NuGet パッケージファイルの配布場所を追加する

「.nupkg ファイルをファイルサーバ上の共有フォルダに置いて共有・再利用する」場合、その共有フォルダのパスを、開発環境に事前に設定しておく必要があります。

とうのも、通常は、NuGet パッケージの使用を示す "パッケージ参照" には、NuGet パッケージの名前 (ファイル名) のみをプロジェクトファイル内に記述するから（パッケージファイルへのフルパスなどは記載しないから）です。

このように、NuGet パッケージファイルを共有・配布のために配置しておく "場所" (今回の説明のようにファイルシステム上であったり、nuget.org のような API サーバー上であったり) を、NuGet パッケージファイルの**「配布場所」**と呼ぶことにします。

ということで、「NuGet パッケージファイルの配布場所」としてファイルサーバ上の共有フォルダを開発環境に設定する手順を見ていきましょう。

## dotnet CLI の場合

残念なことに、`dotnet` コマンドを使用してパッケージファイルの配布場所を追加する標準的な方法は用意されていないようです。
Windows OS を使用している場合は、別途 [`nuget` コマンドをダウンロード](https://www.nuget.org/downloads)、インストールしておくことで、`nuget` コマンドを介して設定することは可能なようです。

それ以外の場合は、NuGet 関連の設定ファイル (XML 形式のテキストファイルです) を直接編集して、パッケージファイルの配布場所を追加することになるようです。

NuGet 関連の設定ファイルのパスは以下のとおりです。

- Windows の場合... `%appdata%\NuGet\NuGet.Config`
- macOS/Linux の場合.. `~/.config/NuGet/NuGet.Config` または `~/.nuget/NuGet/NuGet.Config`

この設定ファイル (.config) を任意のテキストエディタで編集し、`<packageSources>` ノードに、配布場所の表示用の名称と、配布場所のフォルダパスを示した `<add key="..." .../>` ノードを追加して」保存します。

![fig0-7b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/8736b53f-70ad-3dd0-6705-9609e38b3d78.png)

下記 URL も参考になるでしょう。

- [一般的な NuGet 構成 | Microsoft Docs](https://docs.microsoft.com/ja-jp/nuget/consume-packages/configuring-nuget-behavior)

## Visual Studio の場合

Visual Studio のメニューの [ツール(T)]-[オプション(O)...] を開き、[NuGet パッケージマネージャー] > [パッケージソース] のカテゴリを開きまして、そこにパッケージファイルの配布場所を追加します。
![fig0-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/3366b4d5-336a-e767-d429-58c1131cd7f8.png)

# "MarqueeLib" パッケージを追加してみよう!

開発環境に、NuGet パッケージファイルの配布場所を追加できたら、あとは、その配布場所に配した NuGet パッケージファイルを利用するだけです!

## dotnet CLI の場合

"MarqueeLib" パッケージを利用したい、Blazor アプリケーションのプロジェクトファイル (.csproj) があるフォルダにカレントフォルダを移します。

その上で、`dotnet add package` コマンドでパッケージ名を指定してプロジェクトにパッケージ参照を追加すればよいです。

```shell
> dotnet add package MarqueeLib
```

※その他、.csproj ファイルを直接、テキストエディタで編集して、パッケージ参照を追記してもよいです。

- 参照: [https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-add-package](https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-add-package)


## Visual Studio の場合

まず "MarqueeLib" パッケージを利用したい、Blazor アプリケーションのプロジェクトを開きます。

その上で、Visual Studio のパッケージマネージャコンソールからでもよいですし、下図のように GUI から操作してもよいので、先に追加したパッケージファイルの配布場所がパッケージソースに含まれていることを確認の上、"MarqueeLib" パッケージを見つけてインストールすればよいです。
![fig0-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/ffd054cd-3b3d-8c57-acd1-e657e8e50225.png)

## ここからは dotnet CLI でも Vsiaul Studio でも同じ作業

無事、"MarqueeLib" パッケージをアプリケーションのプロジェクトに追加できたら、Marquee コンポーネントが使えます!
![fig0-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/a99205b4-6658-c71a-9726-fd22271679a4.png)

# まとめ

このように、Blazor コンポーネントを、再利用可能な NuGet パッケージファイルにまとめ、他のプロジェクトでも利用可能にすることができました。

やり方は単純で、再利用する Blazor コンポーネントを独立したクラスライブラリプロジェクトに切り出してしまえば、あとは「パッケージ化する」というコマンドを実行するだけでした。

作成した NuGet パッケージファイルは、ファイルサーバ上の共有フォルダに置いておくような形でも、配布・共有が可能です。（他にも色々配布方法はあります）

作成した NuGet パッケージファイルを nuget.org 以外の配布場所に置く場合は、開発環境に、その配布場所を追加する設定が必要です。

ひとたび開発環境へのパッケージ配布場所の追加登録さえ済ませておけば、あとは、プロジェクトに "パッケージ参照" を追加するだけで、Blazor コンポーネントを再利用できます。

いかがでしょう?

このように**非常にシンプルな方法**で、**プログラムの再利用ができる**ところも、私にとっての Blazor の魅力のひとつです!

Happy Coding! :)