JavaScript イニシャライザが読み込まれない謎の現象
先日、自分が作成した NuGet パッケージに収録した、Blazor 用の JavaScript イニシャライザ .js ファイルが、どういうわけかブラウザに読み込まれない、という不具合に遭遇しました。
なにぶん、Blazor の .NET ランタイムが実行されるよりも前に発生している事象であるため、Visual Studio 等のデバッガでは調査できません。また、ブラウザの開発者ツールのネットワークタブを確認するも、当該 .js ファイルに対するアクセスが出現しないのです。ここで当該 .js ファイルへのアクセスは発生しつつも HTTP 404 Not Found であるとか、何らか HTTP ステータスが返ってきていれば、そこから「あ、URL パスがなんかおかしい」とか、トラブルシュートの足がかりになるものですが、そもそもアクセスが発生していないのですから首をかしげるばかりです。試しにと、curl コマンドで当該 .js にアクセスすると、これはなんと、成功するのです。まったく見当がつきません。
いやぁ困った、困った、と途方に暮れつつも、公式ドキュメントで Blazor のスタートアップシーケンスについて見直していると、「診断トレース情報を On にする」という記述を見つけました。
そこで、Blazor のランタイムに対し、診断トレース情報の出力を有効にオプション指定する方法を試すことにしました。
診断トレース情報の有効化の手順
公式ドキュメントでは、JavaScript イニシャライザ内で、診断トレース情報の出力を On にする手順が説明されていますが、今回はそもそも JavaScript イニシャライザがブラウザに読み込まれませんので、この方法では太刀打ちできません。
幸い、Blazor の手動実行時に、診断トレース情報の出力を On にすることができることがわかりました。具体的には、以下のように実装していきます。
まずはじめに、Blazor のフォールバックページには、例えば Blazor WebAssembly の場合は、以下のように Blazor のランタイムを読み込む <script />
タグがマークアップされていると思います。
<!DOCTYPE html>
<html lang="en">
...
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
この Blazor のランタイム読み込みの <script />
要素に autostart="false"
の属性を追加して Blazor が自動では起動しないように設定します。その上で、以下のように、手動で Blazor を起動する JavaScript コードを追加します。
<!DOCTYPE html>
<html lang="en">
...
<!-- autostart=false を追加し Blazor が自動起動しないようにする👇 -->
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<!-- 👇 以下の script 要素を追加 -->
<script>
// オプション指定して Blazor を手動で起動
Blazor.start({
// ランタイム構成時のコールバック関数をオプションに指定し...
configureRuntime: (builder) =>{
// diagnosticTracing オプションを true に設定
builder.withConfig({ diagnosticTracing: true });
}
});
</script>
</body>
</html>
次は、ブラウザの開発者ツールを開き、コンソールタブにて、出力レベルの「詳細」を On にします。
Blazor の診断トレース情報の出力は、console.debug
メソッドで行なわれるようです。そのため、ブラウザのコンソールの、「詳細」の出力レベルが既定の Off のままだと、せっかくの診断トレース情報が可視化されません。
以上、この状態で、この Blazor アプリケーションを再読み込みすると、以下のように、ブラウザのコンソールに、Blazor 起動時の診断トレース出力が現れるようになります。
...
MONO_WASM: Loaded:mscorlib.o0184ey5ia.wasm as assembly size 49429 from https://localhost:7087/_framework/mscorlib.o0184ey5ia.wasm
logging.ts:24 MONO_WASM: Loaded:netstandard.hb3h2rr8mk.wasm as assembly size 90389 from https://localhost:7087/_framework/netstandard.hb3h2rr8mk.wasm
logging.ts:24 MONO_WASM: Loaded:BlazorWasmApp1.hhhdptzpqg.wasm as assembly size 12053 from https://localhost:7087/_framework/BlazorWasmApp1.hhhdptzpqg.wasm
logging.ts:24 MONO_WASM: Loaded:icudt_CJK.tjcz0u77k5.dat as icu size 956416 from https://localhost:7087/_framework/icudt_CJK.tjcz0u77k5.dat
logging.ts:24 MONO_WASM: Loaded:System.Private.CoreLib.fk089ohxy8.wasm as assembly size 4641561 from https://localhost:7087/_framework/System.Private.CoreLib.fk089ohxy8.wasm
logging.ts:24 MONO_WASM: Initializing mono runtime
logging.ts:24 MONO_WASM: mono_wasm_load_runtime
logging.ts:24 MONO_WASM: bindings_init
logging.ts:24 MONO_WASM: all assets are loaded in wasm memory
logging.ts:24 MONO_WASM: mono_wasm_after_user_runtime_initialized
logging.ts:24 MONO_WASM: postRunAsync
logging.ts:26 MONO_WASM: Attempting to import 'https://localhost:7087/_content/Toolbelt.Blazor.GetProperty.Script/Toolbelt.Blazor.GetProperty.Script.lib.module.js' for ../_content/Toolbelt.Blazor.GetProperty.Script/Toolbelt.Blazor.GetProperty.Script.lib.module.js
logging.ts:24 MONO_WASM: added module imports 'blazor-internal'
...
診断トレース情報からわかったこと
上記例は、正常に動作している別の例を引用してきたものですが、上記抜粋中、最後のほうに、Attempting to import 'https://localhost:7087/_content/Toolbelt.Blazor.GetProperty.Script/Toolbelt.Blazor.GetProperty.Script.lib.module.js' for ../_content/Toolbelt.Blazor.GetProperty.Script/Toolbelt.Blazor.GetProperty.Script.lib.module.js
というトレース情報が出力されており、ここから、
- 指定の相対 URL で示される JavaScript イニシャライザの読み込みを行なおうとしていること、
- そしてその相対 URL を絶対 URL に解決したあとの URL が記載されていること
が読み取れます。
冒頭で紹介したトラブルが発生していたケースでは、JavaScript イニシャライザの相対 URL は期待どおり正しかったものの、そこから導出された絶対 URL がとんでもない値になっていることが診断トレース情報に表示されました。結果、URL として妥当ではない文字列を import に渡していたので、HTTP 要求を作るレベルですらなく、それで開発者ツールのネットワークタブにはなんの挙動も記録されることがなかったようでした。
このことが手がかりとなって、問題のケースはどうにか解決に漕ぎ着けることができました (ブラウザの <head />
要素内に設定しておくべき <base />
要素が諸事情で設定されていなかった)。
おわりに
今回は起動シーケンス中の診断トレース情報だけ見ていたため、自分はよくわかっていないものの、他の Blazor の動作の際も、都度都度、診断トレース情報が出力されるのかもしれません。Blazor ランタイムの診断トレース情報なんて、なかなかその必要に迫られることはないかもしれませんが、Blazor の中で起きていることが垣間見え、やや興味をそそられる部分でありました。