Blazor WebAssembly アプリは、GitHub Pages 上にも配置できる
Blazor は C# で SPA を実装するフレームワークやランタイムでありますが、とりわけ Blazor の WebAssembly 版は、JavaScript 製の SPA フレームワークと同じくブラウザ上で動作します。
そのため、静的コンテンツを配置・配信可能な Web サーバーであれば何であっても、そのサーバー上に Blazor WebAssembly アプリの発行成果物を配置すれば、それをブラウザで開いて動作させることができます。
実際、Blazor WebAssembly アプリは、GitHub Pages 上に配置することもできます。
自分が GitHub Pages 上に配置・公開している Blazor WebAssembly アプリを以下に2つほど例示しておきます。
Awesome Blazor Browser
https://jsakamoto.github.io/ (私個人のポートフォリオサイト)
だがしかし GitHub Pages 用に調整するのがダルい...
さて、Blazor WebAssembly (に限らず、JavaScript 製の各種 SPA フレームワークでも同じだと思いますが) を GitHub Pages 向けに "発行" するのは、難しくはないのですが、いくつか "調整" 作業が必要です。
- (GitHub Pages が備える Jekyll 変換は使わないので)
.nojekyll
ファイルを追加 - Git による迂闊な変換がされないよう
.gitattribute
ファイルを作成 -
index.html
中の<base href="..."/>
が指すベース URL を、GitHub Pages に配置後の URL に合せて書き換え ( (a) 発行後にindex.html
を書き換えるか、(b) 事前に (index.html
はもちろん)launchSettings.json
も含めてプロジェクトそのもののベース URL を変更しておくか、のいずれか) - (
index.html
をコピーして)404.html
ファイルを追加
ひとつひとつは大した作業ではないです。
っていうか、機械的な単純作業の部類かと思います。
ですが、index.html
の変更も含むようなアプリの改訂後に再発行、など、発行作業を繰り返し行なうとき、こんな単純作業を手作業で行なうのもなんだかなぁ、と、常々思っていました。
GitHub Pages 向け発行作業を自動化 & NuGet パッケージ化
そこで、ある日ついに一念発起して、Blazor WebAssembly アプリを GitHub Pages 向けに発行する作業を自動化し、NuGet パッケージとして公開しました。
その NuGet パッケージがこちらです。
ということで、この NuGet パッケージを使って、Blazor WebAssembly アプリを GitHub Pages 向けに発行する作業を説明します。
1. NuGet パッケージ参照をプロジェクトに追加
まずは、なにはともあれ、対象の Blazor WebAssembly プロジェクトに、この NuGet パッケージ参照を追加します。
Windows OS 上で Visual Studio を使って開発中であれば、Visual Studio の NuGet パッケージマネージャウィンドウから "PublishSPAforGitHubPages.Build" を検索して追加したり、
あるいは Visual Studio の NuGet パッケージマネージャコンソールウィンドウにて、追加することもできます。
PM> Install-Package PublishSPAforGitHubPages.Build
Visual Studio Code など任意のエディタで作業中でしたら、対象の Blazor WebAssembly のプロジェクトファイル (.csproj) を直接編集し、適当な <ItemGroup>
ノードの中に (なければ <ItemGroup>
ノードの追加も含めて) 以下のように NuGet パッケージ参照の記述を追記すればよいでしょう。
...
<ItemGroup>
...
<PackageReference Include="PublishSPAforGitHubPages.Build" Version="1.1.0.1" />
...
</ItemGroup>
...
もちろん、dotnet CLI で NuGet パッケージ参照を追加することもできます。
$ dotnet add package PublishSPAforGitHubPages.Build
2. GHPages
MSBuild プロパティを指定して発行すれば OK!
ひとたび PublishSPAforGitHubPages.Build
をプロジェクトに追加した以降は、そのプロジェクトを、GHPages
MSBuild プロパティに true
を指定して発行するだけです。
例えば dotnet CLI を使って発行する場合は以下のように "-p:GHPages=true" を付けて実行すればよいです。
$ dotnet publish -c:Release -p:GHPages=true
Visual Studio の GUI からファイルへ発行する場合は、発行プロファイルファイル (.pubxml) か、あるいは、プロジェクトファイル (.csproj) を事前に編集しておいて、MSBuild スクリプト内に GHPages
MSBuild プロパティに true
を指定しておくとよいでしょう。
<PropertyGroup>
<GHPages>true</GHPages>
</PropertyGroup>
以上、このように GHPages=true の MSBuild プロパティを指定して発行するだけで、発行先のフォルダには、本投稿の冒頭で説明したとおりの、GitHub Pages 向けの調整がすべて施された発行成果物ファイルが生成されるようになります。
オフライン対応 PWA でも大丈夫!
さてところで、GitHub Pages に配置する Blazor WebAssembly アプリを、オフライン対応の PWA にする場合、index.html
を変更するだけ(例:内部のベース URL を変更)で、それ以上は何もしないでいると、その Blazor PWA はエラーとなって動作しません。
通常の Blazor PWA プロジェクトでは、その発行時に各コンテンツファイルのハッシュを計算して service-worker-assets.js
ファイルにそのハッシュ値を格納します。そして、Web ブラウザはその Blazor PWA を読み込む際に service-worker-assets.js
ファイルと付き合わせて整合性チェックを行います。
// 📜 service-worker-assets.js
self.assetsManifest = {
"assets": [
{
"hash": "sha256-lqehqsKUaAnnNozj4bnXdM6UlKdzXsxJnVsMN+SjhAY=",
"url": "index.html"
},
...
そのため、index.html
だけ変更して service-worker-assets.js
を何も更新しないと、整合性チェックに失敗し、その Blazor PWA は動作しなくなります。
幸い、この PublishSPAforGitHubPages.Build
パッケージ(2021年12月リリースの v.1.3.5 ないしはそれ以降)は、発行時に service-worker-assets.js
ファイル内のハッシュ値を適切に自動更新します。そのため、最新版のPublishSPAforGitHubPages.Build
パッケージを使用して Blazor PWA を GitHub Pages にデプロイする場合は、上記の整合性チェックについて開発者が気にする必要がありません。PublishSPAforGitHubPages.Build
を使っていれば、それらの心配は無用です。
Brotli 圧縮も有効に!
さらに、この NuGet パッケージ PublishSPAforGitHubPages.Build
(2021年12月リリースの v.1.2.0 ないしはそれ以降)には、さらなる特典があります。
なんと、GitHub Pages に配置した Blazor WebAssembly アプリにおいて、事前 Brotli 圧縮されたアセンブリ読み込みが有効になるのです!
実は Blazor WebAssembly プロジェクトを発行すると、素の .NET アセンブリファイル (.dll) に加えて、GZip 圧縮した同名のファイル (.dll.gz) および Brotli 圧縮した同名のファイル (.dll.br) が同時に生成されています。
ただ、これら事前圧縮されたアセンブリファイルは、そのままでは採用されません。
Blazor WebAssembly アプリのローダー側で、明示的に .dll.br を Web サーバーから取得し、Brotli 圧縮を伸張する必要があるのです。
詳しくは下記公式ドキュメントに解説があります。
最新版の PublishSPAforGitHubPages.Build
を使って、GHPages=true を指定しての発行を行なうと、発行処理の一環として、発行後の index.html
ファイルを書き換えて、事前 Brotli 圧縮されたアセンブリ読み込みを行なう JavaScript コードの注入が行なわれるようになる仕掛けです。
...
<!-- 👇 autostart="false" 属性が書き加えられる -->
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<!-- 👇 以下 2行の script 要素が追加される -->
<script src="decode.min.js"></script>
<script src="brotliloader.min.js"></script>
</body>
Blazor WebAssembly は、どうしても .NET アセンブリファイル群 (.dll) の総サイズが膨らみがちです。
もっとも、二回目以降のアクセスでは、初回アクセス時にブラウザの Cache Storage に保存されたデータを使うので、さくっと開きます。
ですが、そうは言っても、とにかく初回アクセス時には、どうしてもそれら多くの .NET アセンブリファイル群 (.dll) を転送せざるを得ず、通信量がかさみ、初期ロード時間が長くなる懸念があります。
その点、事前 Brotli 圧縮されたアセンブリファイル (.dll.br) を取得するようにすることで、結構なサイズの通信量を削減することができ、初回アクセス時の初期ロード時間の短縮が期待できます。
おまけ: GitHub Actions を使った配置
以上、Blazor WebAssembly アプリを GitHub Pages 向けに発行するにあたり、つまらぬ調整作業を一手に引き受ける上に、事前 Brotli 圧縮されたアセンブリファイル読み込み機能も織り込んでしまう NuGet パッケージ PublishSPAforGitHubPages.Build
の紹介でした。
なお、この PublishSPAforGitHubPages.Build
パッケージと GitHub Actions を組み合わせると、さらに GitHub Pages への配置が簡単になります。
例えば以下のような GitHub Actions 用の YAML ファイルを、リポジトリの .github/workflows
フォルダに収録しておくと、GitHub に push するたびに自動で、gh-pages
ブランチに Blazor WebAssembly アプリを配置してくれるようになります。
name: github pages
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# Checkout the code
- uses: actions/checkout@v2
# Install .NET Core SDK
- name: Setup .NET Core
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
# Publish the site
- name: Publish
run: dotnet publish (プロジェクトフォルダ)/(プロジェクト名).csproj -p:GHPages=true -c:Release -o:public
# Deploy the site
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: public/wwwroot
force_orphan: true
これでより手軽に、自作の Blazor WebAssembly アプリを、GitHub Pages 上で公開できるようになりますね!
Learn, Practice, Share!