BlazorのPageTitleはJSでDOMを書き換えている

Blazorのタイトル反映が遅い気がする

Blazorでページタイトルを設定する場合PageTitleを使います。

<PageTitle>Hello World!</PageTitle>

<h1>Hello World!</h1>

こんな感じで書けるんですが、初回にブラウザで見たときにこのタイトルが反映されるまで若干ラグがあるな~と思ってました。反映される前は何が表示されているかというとindex.htmlなどのタイトルです。

JSでDOMを書き換えている

PageTitleは最終的にHeadOutletに流し込まれます。ちなみに、BlazorのテンプレートにはすでにHeadOutletが組み込まれています。たとえば、Blazor WebAssemblyには以下があります。

builder.RootComponents.Add<HeadOutlet>("head::after");

このHeadOutletの実装を見てみるとこうなっています。

private const string GetAndRemoveExistingTitle = "Blazor._internal.PageTitle.getAndRemoveExistingTitle";

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        _defaultTitle = await JSRuntime.InvokeAsync<string>(GetAndRemoveExistingTitle);
        StateHasChanged();
    }
}

OnAfterRenderAsyncの初回レンダリング後、DOMのtitleをJSRuntime経由で削除&保持してからもう一度描画しています。なのでなんかタイミングが遅い感じがするんですね。

タイトルだけ特別

HeadOutletは、PageTitleのほかにHeadContentからも中身を受け取ります。ただ、タイトル以外はJSで処理されません。そのまま描画されるだけです。

これはタイトルがindex.htmlなどに最初から設定されていることがほとんどだからでしょう。重複を避けつつ既存値をデフォルト値として引き継ぎたいため、JSで一度DOMから回収してるんですね。

参考