torum

主に開発中のアプリにまつわる技術系の事。

BlazorのWebAssemblyをレンタルサーバーやGitHubのPagesにデプロイしてみた

BlazorのWebAssembly、つまり.NETのC#で作ったアプリがブラウザ内で動いてしまうという変態・・・もとい、驚きの技術がある訳ですが、今まで特にBlazorで作りたいものも無かったので、2019年に正式版がリリースされていたにも関わらず、まだ触っていませんでした。

そこで、今日、ちょっと息抜きにチャレンジしてみました。先ほど、WinUI 3 - Project Reunion 0.8 Previewを試したのですが、強烈に脱力するほどダメだったので、お口直しです。正直、期待しないようにしてましたが、結果としては、色々あったけど、.NETのC#ソースコードがそのままブラウザで動くとか変態すぎて、ニヤニヤが止まりませんでした。特に、自分はここ10年ぐらいWeb系の開発から離れている事もあり、良い気分転換になりました。

Blazorには、サーバーサイドでの実行に依存するBlazor Serverと、クライアントサイドだけで単体動作するBlazor WebAssemblyの二種類があり、クライアント(ブラウザ)だけで動くstandaloneのWebAssemblyも作れるという話し。サーバー版を使うと、MicrosoftのAzureとか、クラウドのサービスにロックインされるのが嫌なので、使いません。(データを保存して操作するような場合は何らかのクラウドのサービスを使ってAPIサーバー側も作らないとなりませんが、既存の公開されてるサードパーティーAPI- 天気予報APIとかブログ投稿APIとか - を使うだけなら問題ない)

クライアントサイドだけで動くstandaloneのWebAssemblyが可能という事は、普通のレンタルサーバーにファイルを置くだけで動作するはずです。

では、試してみようではないか、と。しかし、マイクロソフトの公式にも、様々なサイトにも、静的ファイルを普通のレンタルサーバーにFTPでアップロードしてデプロイする、なんて情報は一切どこにもありません。Visual Studioを使ってAzureにデプロイとかFirebaseにデプロイ、IISサーバーにデプロイ、そんな話しばかりです。みんな、クラウドとかで、サーバーサイドを使う前提なのですね。

まぁBlazorの大きな利点は、クライアント側のフロントエンドとサーバー側のバックエンド実装を、JavaScriptとかを使わずに、同じC#ソースコードで共通化できる、という事ですからまぁ当然ですね。クラス定義とかそのまま使いまわせるとかムネアツ。なので、わざわざstandaloneに切り分けてブラウザで全てを処理させる必要性はオフラインでも動作するようにする以外、あんまりありません。

しかし、私は古い人間なので、昔のように、FTPソフトを使ってCGI/Perlスクリプトをアップロードしたりするようなのを試したいのです(化石人間)。いや、どうせやるなら、誰もやってない事をやりたいではないですか。

そこで早速、Visual Studioで、BlazorのWebAssemblyプロジェクトを選択して、シンプルなサンプルアプリを作ります。そして、Buildメニューから発行を選んで、フォルダに書き出します。で、publishフォルダに生成された、wwwroot以下にあるファイルを全てFTPでアップロードします。

ここまで5分とかかりません。

その際、ルートではなく、サブディレクトリ内にアップロードする場合は、index.htmlの

<base href="/" />

を、対応するディレクトリのパスに書き直します。この辺りはMicrosoftの公式サイト含め、情報が転がっていました。

さて、昔のようにパーミッションの設定とか考えずに、おもむろにブラウザでアクセスしてみます。

なんということでしょう。

Loading...

という表示のまま、何も起きません。色々と検索してみましたが、そもそも静的ファイルをアップロードしてデプロイなんて例はどこにもないため、とっかかりが見つかりません。一番関連がありそうだったのは、以下のページ。

stackoverflow.com

ファイル共有サービスにデプロイしたいけど、Loading...となったまま動かない、というもの。しかし、答えは出て無く、未解決のままです。

once you use dotnet publish and only see "Loading..." check your js console. You will find some errors because of some missing files.

しかし、ヒントは、ブラウザのJavaScriptコンソールを見れば何かエラーが出てるかもしれないよ、というコメント。

f:id:torum:20210701035618j:plain

ビンゴでありました。

blazor.webassembly.js:1 Failed to find a valid digest in the 'integrity' attribute for resource 'http://mysite/_framework/dotnet.5.0.7.js' with computed SHA-256 integrity 'y+FDN+tQsjEDvbZn4gnCxFrs09PIV++bJUd/ZZ/TZZ4='. The resource has been blocked.

どうもハッシュのダイジェストで整合性を確認しているようでそれがミスマッチだから読み込まないよ、と。なんでやねん。

エラーメッセージで検索すると、

github.com

同様のエラーのIssueが見つかりました。解決したようですが、

Replaced content of the .gitattributes file with * binary and deleted everything from publish folder except this file and republished and pushed everything is working fine now.

これ、Gitの話しですね。つまり、GitHubのPagesとかでホスティングする際の話し。Gitで、.gitattributes使って、* binaryを指定して、ファイルをバイナリーとして扱うように指示をすれば良い、という事です。

なるほど、分かりません。さらに調べると、関連のIssueで、

github.com

 

GitがCRLF(つまり改行コード)を変換している為、それがハッシュ値に干渉している、という話し。なるほどなるほど。

もしかして・・・昔の懐かしのFTPでの転送でバイナリーモードとアスキーモードってあったよな!と。FTPアスキーモードでは改行コードが変換されます。このせいで、PerlCGIスクリプトが動かない、なんて昔よくありました。

早速、FileZillaFTPソフト)の設定で、自動判定のAutoからBinaryモードに変更してアップロードし直します。ダメです、変化ありません・・・と、またもや昔懐かし、「キャッシュのクリア」を思い出しました。ブラウザのキャッシュに残っているに違いない。

ごにょごにょ・・・

f:id:torum:20210701040846j:plain

ス・テ・キ。

 

実際に動いているサンプルはここです。

http://torum.byethost15.com/

Chromeだけでなく、同系統のEdgeとBrave、MozillaFireFoxでも当然のように動きました。なお、iPhoneでは、iOS13以降でしか動かないようで、手持ちの古いiPhoneでテストした結果、iOS 12.4.9が最新となるiPhone6やそれ以前のSafariChromeでは動きませんでした。

 

なんかもうモバイルアプリもウェブアプリも、BlazorのWebAssemblyでいいじゃん、という気がしてきました。