「CSSの分離」で、さらに再利用可能な NuGet パッケージが作りやすく

# Blazor のコンポーネントはパッケージ化がカンタン

昨年の Blazor Advent Calendar の投稿として[「Blazor のコンポーネントをパッケージ化して再利用する」](https://qiita.com/jsakamoto/items/4c4520a0b73d3f30d95a)という記事を書きました。

上記記事では、`<Marquee />` というマークアップで「流れる文字」表示を実現する 「MarqueeLib」というライブラリを、**NuGet パッケージファイル (.nupkg)** という形態に仕立てて再利用する流れを解説しました。
このように Blazor のコンポーネントは、**他の人に配布・共有**したり、**他のプログラムから再利用**したりすることが、**容易にできる**のが利点のひとつかと思います。

あれから一年。

今年はさらに「MarqueeLib」ライブラリを強化し、もうちょっと見た目を派手にすることにしました。

# CSS ファイルを追加して見た目を調整

ということで、まず手始めに、「流れる文字」を実現している Blazor コンポーネント `Marquee.razor` のソース内にて、実装の DOM 要素に CSS クラス名を設定します。

```html:Marquee.razor
<!-- 👇 スタイル当てるために CSS クラス名 "marquee" を付与 -->
<div class="marquee" ...>
...
</div>
```

続けて、見た目を派手にするための CSS スタイルシート `style.css` を、`MarqueeLib` クラスライブラリプロジェクト内の `wwwroot` フォルダに追加します。

`style.css` の内容は下記のとおりとしました。

```css:wwwroot/style.css
.marquee {
    border: solid 2px #ff00dc; /*👈 ピンク色の枠線をつけて、*/
    background-image: url(background.png); /*👈 背景画像を設定。*/
    padding: 8px 0;
}
```

仕上げに背景画像となる `backgroumd.png` を作成して、同じく、`MarqueeLib` クラスライブラリプロジェクト内の `wwwroot` フォルダに配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/3f21683a-3c72-f5bb-3ef2-011f0d588d70.png)
最後に、(今回は機能追加・改善的な変更なので) パッケージのマイナーバージョン番号を加算して (`MarqueeLib.cspoj` ファイル内の `<version>` ノードを追加または変更します)、

```xml:MarqueeLib.cspoj
...
<PropertyGroup>
  ...
  <!-- 👇 version ノードにパッケージのバージョンを記載 -->
  <Version>1.1.0</Version>
  ...
</PropertyGroup>
...
```

パッケージ化を実行します。

```shell
$ dotnet public -c:Release
```

これで、Release ビルドの出力フォルダのしたに、`MarqueeLib.1.1.0.nupkg` パッケージファイルが生成されますから、このパッケージファイルを配布すれば OK です。

# しかし、せっかくのスタイルが当たらない...!

こうして見た目を派手にバージョンアップした「MarqueeLib」パッケージを配布したのですが...

「サカモトさーん、Marquee の見た目、前のバージョンと変わっていないんですけどー」

はっ!

しまった、そうでした!

たしかに新バージョンのパッケージには、背景画像と CSS スタイルシートファイルが同梱されてはいるのですが、**それを HTML ドキュメントにて読み込み**しないとならないのでした。

今回のシナリオでは、つまり、単に NuGet パッケージ参照を追加または更新してコンポーネントのマークアップを記述する**だけ、ではダメ**で、さらに、`index.html` 等の HTML ドキュメントに、NuGet パッケージ内に同梱されているアセットの読み込みを**手作業で追記**しないとならないのです。

今回の例ですと、`index.html` (ないしは `_Host.cshtml` とか、それに相当する HTML ドキュメント) に、以下のように追記の必要があるのでした。

```html:index.html
<html>
<head>
  ...
  <!-- 👇 以下の1行を追記 -->
  <link href="_content/MarqueeLib/style.css" rel="stylesheet" />
  ...
```

※`"_content/{NuGetパッケージ名}/{同梱されているアセットの相対パス}"` で、NuGet パッケージに同梱されたアセットを読み込みできます。

うーん...

このように、NuGet パッケージとして配布した Blazor コンポーネントを利用してもらうにあたり、`index.html` にも CSS スタイルシートファイルの読み込みを、手作業で追記してもらう必要があるのはイマイチな感じがします。

何とかならないでしょうか?

# Blazor ver.5 (.NET 5) ならスッキリ解決!

なんとうれしいことに、Blazor ver.5 (.NET 5) 以降であれば、この「スタイルシートファイルの読み込みを手作業で追記してもらう必要ある」問題をスッキリ解消できます!

具体的には、Blazor v.5.0 からの新機能、**「CSS の分離」**によって問題解決することができます。

なお、「CSS の分離」について詳しくは、先日の @nobu17 さんによる Blazor Advent Calendar 2020 への投稿 [「.NET 5で追加されたBlazorの新機能の説明(サンプル付き)」](https://qiita.com/nobu17/items/7465006ce24a4490183b#1css%E3%81%AE%E5%88%86%E9%9B%A2) がとてもわかりやすいと思います。

ということで、実際にやってみましょう。

## 準備 - 利用する側のアプリの「CSS の分離」機能対応

まずはパッケージを利用する側の Blazor アプリケーションを Blazor v.5 (.NET 5) ベースにバージョンアップをすませておきます。

その際、これが重要なのですが、Blazor v.5.0 からの新機能、**「CSS の分離」**機能が有効になるように `index.html` の対応を済ませておきます。

```html:index.html
<html>
<head>
  ...
  <!-- 👇 下記行があること! -->
  <link href="{プロジェクト名}.styles.css" rel="stylesheet" />
  ...
```

## ライブラリ側

次に、ライブラリ/NuGet パッケージ側です。

まずは `MarqueeLib` クラスライブラリプロジェクトも、.NET 5 化しておきます。

(`MarqueeLib.csproj` ファイル内を編集し、`<TargetFramework>` を `net5.0` に変更、並びに、参照している `Microsoft.AspNetCore.Components.～` 系および `System.～` 系パッケージの参照先バージョンを `5.0.0` に更新)

そして、先ほど `MarqueeLib` プロジェクト追加した CSS スタイルシートファイル `wwwroot/style.css` ですが、このファイルの配置場所と名前を、`Marquee.razor.css` というように、**スタイルを当てたい Blazor コンポーネントのソースファイル名 + ".css"** というファイル名に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/a734f566-cd76-e4b4-89b8-3a8261c00dd3.png)
これは先ほど記載した Blazor v.5.0 からの新機能、「CSS の分離」機能にあわせたファイル構成です。

こうしてパッケージバージョン番号を加算してもういちどパッケージ化し、配布します。

こうして Blazor のバージョンを v.5.0 に揃え、「CSS の分離」を正しく構成した状態で、今一度、`MarqueeLib` NuGet パッケージを参照追加し、`<Marquee Text="Hello, World!" />` を試すと...

![movie-001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/eaacb5dd-5506-de1f-c6a9-041dd6a9e8f9.gif)


おお!

今度は、`index.html` を書き換えること無く、NuGet パッケージ化されたコンポーネントのマークアップを記述するだけで、ちゃんとスタイルが当たります!

# まとめ

このように Blazor v.5.0 (.NET 5) からは、「CSSの分離」機能により、さらに Blazor コンポーネントの NuGet パッケージの利用がカンタンになりました。

加えて、「CSS の分離」ですから、このシナリオで実装した **`Marquee.razor.css` で定義されているスタイル**は、利用している側のアプリをはじめ、**他のコンポーネントに干渉しません**。

つまり `MarqueeLib` NuGet パッケージを利用しているアプリの中で、間違って (!?) `<span class="marquee">...` などと、**CSS クラス名 "marquee"** を使ってしまっても、ピンク色の枠線が付いたりすることがないわけです。

CSS スタイルの干渉を心配することなく、再利用可能な Blazor コンポーネントおよびその NuGet パッケージが、より作りやすくなりましたね。

「CSS の分離」は、先行する他の JavaScript 製フレームワークの類ではずいぶんと以前から提供されている機能・仕組みではあります。
Blazor もついにこれに追いつき、そして Blazor ならではのパッケージ化の容易さと相まって、**Blazor コンポーネントの NuGet パッケージ化がますます楽しくなる**というものです。😊

_Learn, Practice, Share!_