ASP.NET Core Blazor の起動

注意

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の ASP.NET Core 8.0 バージョンを参照してください。

この記事では、Blazor アプリの起動構成について説明します。

サーバー側開発用の ASP.NET Core アプリの構成に関する一般的なガイダンスについては、「ASP.NET Core の構成」をご覧ください。

この記事を通して、アプリ コードが実行される場所を区別するために、サーバー/サーバー側クライアント/クライアント側という用語が使用されます。

  • サーバー/サーバー側: Blazor Web アプリの対話型サーバー側レンダリング (対話型 SSR)。
  • クライアント/クライアント側
    • Blazor Web アプリのクライアント側レンダリング (CSR)。
    • Blazor WebAssembly アプリ。

ドキュメント コンポーネントの例では、通常、対話型レンダリング モードの構成は、コンポーネントの定義ファイル (.razor) 内の @rendermode ディレクティブを使用しては行いません。

  • Blazor Web アプリにおいて、コンポーネントには、コンポーネントの定義ファイル内で、または親コンポーネントから継承された対話型レンダリング モードが適用されている必要があります。 詳細については、「ASP.NET Core Blazor レンダリング モード」を参照してください。

  • スタンドアロン Blazor WebAssembly アプリでは、コンポーネントは示されているように機能し、Blazor WebAssembly アプリ内の WebAssembly 上で常に対話形式で実行されるため、レンダリング モードは必要ありません。

対話型 WebAssembly モードまたは対話型自動レンダリング モードを使用すると、クライアントに送信されたコンポーネント コードを逆コンパイルして検査できます。 プライベート コード、アプリ シークレット、またはその他の機密情報をクライアント側でレンダリングされるコンポーネントに置かないでください。

  • サーバー/サーバー側
    • ホスト型 Blazor WebAssembly アプリの Server プロジェクト。
    • Blazor Server アプリ。
  • クライアント/クライアント側
    • ホスト型 Blazor WebAssembly アプリの Client プロジェクト。
    • Blazor WebAssembly アプリ。

ファイルとフォルダーの目的と場所に関するガイダンスについては、「ASP.NET Core Blazor プロジェクトの構造」をご参照ください。参照先では、Blazor 開始スクリプトの場所と、<head><body> コンテンツの場所についても説明されています。

デモ コードを実行する最善の方法は、ターゲットの .NET のバージョンと一致する Blazor サンプル GitHub リポジトリから、BlazorSample_{PROJECT TYPE} のサンプル アプリをダウンロードすることです。 現時点では、すべてのドキュメント例が同じサンプル アプリに含まれているわけではありませんが、現在 .NET 8 の記事の例のほとんどを .NET 8 サンプル アプリへと移行する作業が行われています。 この作業は、2024 年の第 1 四半期に完了する予定です。

スタートアップ プロセスと構成

Blazor 起動プロセスは、Blazor スクリプト (blazor.*.js) を介して自動かつ非同期に行われます。ここで、* プレースホルダーは次を示します。

  • Blazor Web アプリの web
  • Blazor Server アプリの server
  • Blazor WebAssembly アプリの webassembly

Blazor 起動プロセスは、Blazor スクリプト (blazor.*.js) を介して自動かつ非同期に行われます。ここで、* プレースホルダーは次を示します。

  • Blazor Server アプリの server
  • Blazor WebAssembly アプリの webassembly

スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

Blazor を手動で開始するには:

Blazor Web アプリ:

  • autostart="false" 属性と値を Blazor<script> タグに追加します。
  • Blazor.start() を呼び出すスクリプトを、Blazor<script> タグの後の終了 </body> タグ内に配置します。
  • 静的サーバー側レンダリング (静的 SSR) オプションを ssr プロパティに配置します。
  • サーバー側 Blazor-SignalR 回線オプションを circuit プロパティに配置してください。
  • クライアント側の WebAssembly オプションを webAssembly プロパティに配置してください。
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  ...
  Blazor.start({
    ssr: {
      ...
    },
    circuit: {
      ...
    },
    webAssembly: {
      ...
    }
  });
  ...
</script>

スタンドアロンの Blazor WebAssembly と Blazor Server:

  • autostart="false" 属性と値を Blazor<script> タグに追加します。
  • Blazor.start() を呼び出すスクリプトを、Blazor<script> タグの後の終了 </body> タグ内に配置します。
  • Blazor.start() パラメータには追加のオプションを指定できます。
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  ...
  Blazor.start({
    ...
  });
  ...
</script>

前の例の {BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

JavaScript イニシャライザー

JavaScript (JS) イニシャライザーによって、Blazor アプリの読み込みの前後にロジックが実行されます。 JS イニシャライザーは、次のシナリオで役に立ちます。

  • Blazor アプリの読み込み方法のカスタマイズ。
  • Blazor 開始前のライブラリの初期化。
  • Blazor の設定の構成。

JS イニシャライザーは、ビルド プロセスの一部として検出されて、自動的にインポートされます。 多くの場合、JS イニシャライザーを使用すると、Razor クラス ライブラリ (RCL) を使用するときにアプリからスクリプト関数を手動でトリガーする必要がなくなります。

JS イニシャライザーを定義するには、JS モジュールを {NAME}.lib.module.js という名前のプロジェクトに追加します。{NAME} プレースホルダーは、アセンブリ名、ライブラリ名、またはパッケージ識別子です。 ファイルをプロジェクトの Web ルートに配置します。通常、これは wwwroot フォルダーです。

Blazor Web Apps の場合:

  • beforeWebStart(options): Blazor Web アプリが起動する前に呼び出されます。 たとえば、beforeWebStart は、読み込みプロセスやログ レベルなどのオプションをカスタマイズするのに使用されます。 Blazor Web オプション (options) を受け取ります。
  • afterWebStarted(blazor):beforeWebStart の Promise がすべて解決された後に呼び出されます。 たとえば、afterWebStarted を使用すれば、Blazor のイベント リスナーやカスタム イベントの種類を登録できます。 Blazor インスタンスは、afterWebStarted に引数 (blazor) として渡されます。
  • beforeServerStart(options, extensions): 最初のサーバー ランタイムが開始される前に呼び出されます。 SignalR 回線開始オプション (options) と、発行時に追加された拡張機能 (extensions) を受け取ります。
  • afterServerStarted(blazor): 最初の対話型サーバー ランタイムが開始された後に呼び出されます。
  • beforeWebAssemblyStart(options, extensions): 対話型 WebAssembly ランタイムが開始される前に呼び出されます。 発行時に追加された Blazor オプション (options) と拡張機能 (extensions) を受け取ります。 たとえば、オプションによってカスタムのブート リソース ローダーの使用を指定できます。
  • afterWebAssemblyStarted(blazor): 対話型 WebAssembly ランタイムが開始された後に呼び出されます。

Note

レガシ JS 初期化子 (beforeStartafterStarted) は、Blazor Web アプリでは既定で呼び出 "されません"enableClassicInitializers オプションを使用すれば、レガシ初期化子を実行できます。 ただし、レガシ初期化子の実行は予測できません。

<script>
  Blazor.start({ enableClassicInitializers: true });
</script>

Blazor Server、Blazor WebAssembly、および Blazor Hybrid アプリの場合:

  • beforeStart(options, extensions): Blazor が開始する前に呼び出されます。 たとえば、beforeStart は、読み込みプロセス、ログ レベル、およびホスティング モデルに固有のその他のオプションをカスタマイズするために使用されます。
    • クライアント側の beforeStart は、発行時に追加された Blazor のオプション (options) と拡張機能 (extensions) を受け取ります。 たとえば、オプションによってカスタムのブート リソース ローダーの使用を指定できます。
    • サーバー側の beforeStart は、SignalR 回線開始オプション (options) を受け取ります。
    • BlazorWebView では、オプションは渡されません。
  • afterStarted(blazor): Blazor が JS からの呼び出しを受け取れる状態になった後で呼び出されます。 たとえば、afterStarted は、JS 相互運用呼び出しを行い、カスタム要素を登録することによって、ライブラリを初期化するために使用されます。 Blazor インスタンスは引数 (blazor) として afterStarted に渡されます。

その他の .NET WebAssembly ランタイム コールバック:

  • onRuntimeConfigLoaded(config): ブート構成のダウンロード時に呼び出されます。 ランタイムの開始前に、アプリでパラメーター (構成) を変更できます (パラメーターは dotnet.d.tsMonoConfig です)。

    export function onRuntimeConfigLoaded(config) {
      // Sample: Enable startup diagnostic logging when the URL contains 
      // parameter debug=1
      const params = new URLSearchParams(location.search);
      if (params.get("debug") == "1") {
        config.diagnosticTracing = true;
      }
    }
    
  • onRuntimeReady({ getAssemblyExports, getConfig }): .NET WebAssembly ランタイムの開始後に呼び出されます (パラメーターは dotnet.d.tsRuntimeAPI です)。

    export function onRuntimeReady({ getAssemblyExports, getConfig }) {
      // Sample: After the runtime starts, but before Main method is called, 
      // call [JSExport]ed method.
      const config = getConfig();
      const exports = await getAssemblyExports(config.mainAssemblyName);
      exports.Sample.Greet();
    }
    

どちらのコールバックも Promise を返すことができます。また、promise を待機してから、スタートアップを続行します。

ファイル名については、次のようにします。

  • JS イニシャライザーがプロジェクトの静的アセットとして使われる場合は、{ASSEMBLY NAME}.lib.module.js という形式を使います。{ASSEMBLY NAME} プレースホルダーはアプリのアセンブリ名です。 たとえば、プロジェクトのアセンブリ名が BlazorSample である場合は、ファイルを BlazorSample.lib.module.js という名前にします。 ファイルをアプリの wwwroot フォルダーに配置します。
  • JS イニシャライザーが RCL から使われる場合は、{LIBRARY NAME/PACKAGE ID}.lib.module.js という形式を使います。{LIBRARY NAME/PACKAGE ID} プレースホルダーは、プロジェクトのライブラリ名またはパッケージ識別子です。 たとえば、RCL のパッケージ識別子が RazorClassLibrary1 である場合は、ファイルを RazorClassLibrary1.lib.module.js という名前にします。 ファイルをライブラリの wwwroot フォルダーに配置します。

Blazor Web Apps の場合:

次に示すのは、beforeWebStartafterWebStarted<head> に追加することで、Blazor Web アプリが開始される前と後にカスタム スクリプトが読み込まれる JS 初期化子の例です。

export function beforeWebStart() {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'beforeStartScripts.js');
  document.head.appendChild(customScript);
}

export function afterWebStarted() {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'afterStartedScripts.js');
  document.head.appendChild(customScript);
}

前述の beforeWebStart の例では、Blazor の開始前にカスタム スクリプトが読み込まれることのみが保証されています。 スクリプトで待機中の Promise の実行が Blazor の開始前に完了することは保証されません。

Blazor Server、Blazor WebAssembly、および Blazor Hybrid アプリの場合:

次に示すのは、beforeStartafterStarted<head> に追加することで、Blazor が開始される前と後にカスタム スクリプトが読み込まれる JS イニシャライザーの例です。

export function beforeStart(options, extensions) {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'beforeStartScripts.js');
  document.head.appendChild(customScript);
}

export function afterStarted(blazor) {
  var customScript = document.createElement('script');
  customScript.setAttribute('src', 'afterStartedScripts.js');
  document.head.appendChild(customScript);
}

前述の beforeStart の例では、Blazor の開始前にカスタム スクリプトが読み込まれることのみが保証されています。 スクリプトで待機中の Promise の実行が Blazor の開始前に完了することは保証されません。

Note

MVC および Razor Pages アプリでは、JS イニシャライザーは自動的に読み込まれません。 ただし、アプリのマニフェストをフェッチして、JS イニシャライザーの読み込みをトリガーするスクリプトを、開発者コードに含めることができます。

JS イニシャライザーの例については、次のリソースを参照してください。

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

ライブラリが特定の順序で読み込まれるようにする

カスタム スクリプトを、読み込む必要がある順序で beforeStartafterStarted<head> に追加します。

次の例では、script2.js の前に script1.jsscript4.js の前に script3.js を読み込みます。

export function beforeStart(options, extensions) {
    var customScript1 = document.createElement('script');
    customScript1.setAttribute('src', 'script1.js');
    document.head.appendChild(customScript1);

    var customScript2 = document.createElement('script');
    customScript2.setAttribute('src', 'script2.js');
    document.head.appendChild(customScript2);
}

export function afterStarted(blazor) {
    var customScript1 = document.createElement('script');
    customScript1.setAttribute('src', 'script3.js');
    document.head.appendChild(customScript1);

    var customScript2 = document.createElement('script');
    customScript2.setAttribute('src', 'script4.js');
    document.head.appendChild(customScript2);
}

追加のモジュールをインポートする

JS の初期化子ファイルで最上位の import ステートメントを使用して、追加のモジュールをインポートします。

additionalModule.js:

export function logMessage() {
  console.log('logMessage is logging');
}

JS 初期化子ファイル (.lib.module.js):

import { logMessage } from "/additionalModule.js";

export function beforeStart(options, extensions) {
  ...

  logMessage();
}

マップをインポートする

マップのインポートは、ASP.NET Core と Blazor でサポートされています。

ドキュメントの準備完了時に Blazor を初期化する

次の例では、ドキュメントの準備が整うと Blazor が起動されます。

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  document.addEventListener("DOMContentLoaded", function() {
    Blazor.start();
  });
</script>

前の例では、{BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

手動で起動した結果として得た Promise に連結する

JS 相互運用の初期化など、追加のタスクを実行するには、then を使用して、手動で Blazor アプリを起動させた結果として得た Promise に連結します。

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start().then(function () {
    ...
  });
</script>

前の例では、{BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

Note

Blazor の開始後にライブラリで追加のタスクを自動的に実行するには、JavaScript イニシャライザーを使います。 JS イニシャライザーを使う場合は、ライブラリのコンシューマーが JS の呼び出しを Blazor の手動起動にチェーンする必要はありません。

クライアント側のブート リソースを読み込む

アプリがブラウザーに読み込まれると、アプリによってサーバーから次のブート リソースがダウンロードされます。

  • アプリをブートストラップする JavaScript コード
  • .NET ランタイムとアセンブリ
  • ロケール固有のデータ

loadBootResource API を使用して、これらのブート リソースの読み込み方法をカスタマイズします。 loadBootResource 関数によって、組み込みのブート リソース読み込みメカニズムをオーバーライドします。 次のシナリオで loadBootResource を使用します。

  • タイムゾーン データや dotnet.wasm などの静的なリソースを、CDN から読み込む。
  • HTTP 要求を使用して圧縮されたアセンブリを読み込み、サーバーからの圧縮コンテンツのフェッチをサポートしていないホストのクライアントに展開する。
  • fetch 要求を新しい名前にリダイレクトして、リソースを別の名前に設定する。

Note

外部ソースは、ブラウザーがクロスオリジンのリソースの読み込みを許可するために必要なクロス オリジン リソース共有 (CORS) ヘッダーを返す必要があります。 通常、既定では、必要なヘッダーが CDN によって提供されます。

loadBootResource パラメーターは次の表に表示されます。

パラメーター 説明
type リソースの型。 許容される型としては、assemblypdbdotnetjsdotnetwasm、および timezonedata があります。 カスタム動作の型のみ指定する必要があります。 loadBootResource に指定されていない型は、既定の読み込み動作に従ってフレームワークによって読み込まれます。 dotnetjs ブート リソース (dotnet.*.js) は、既定の読み込み動作を表す null、または dotnetjs ブート リソースのソースの URI を返す必要があります。
name リソースの名前。
defaultUri リソースの相対 URI または絶対 URI。
integrity 応答で予想されるコンテンツを表す整合性文字列。

loadBootResource 関数では、URI 文字列を返して、読み込みプロセスをオーバーライドできます。 次の例では、bin/Release/{TARGET FRAMEWORK}/wwwroot/_framework からの次のファイルは https://cdn.example.com/blazorwebassembly/{VERSION}/ の CDN から提供されます。

  • dotnet.*.js
  • dotnet.wasm
  • タイムゾーン データ

{TARGET FRAMEWORK} プレースホルダーはターゲット フレームワーク モニカー (たとえば、net7.0) です。 {VERSION} プレースホルダーは共有フレームワーク バージョン (たとえば、7.0.0) です。

Blazor Web アプリ:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        console.log(`Loading: '${type}', '${name}', '${defaultUri}', '${integrity}'`);
        switch (type) {
          case 'dotnetjs':
          case 'dotnetwasm':
          case 'timezonedata':
            return `https://cdn.example.com/blazorwebassembly/{VERSION}/${name}`;
        }
      }
    }
  });
</script>

スタンドアロン Blazor WebAssembly:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      console.log(`Loading: '${type}', '${name}', '${defaultUri}', '${integrity}'`);
      switch (type) {
        case 'dotnetjs':
        case 'dotnetwasm':
        case 'timezonedata':
          return `https://cdn.example.com/blazorwebassembly/{VERSION}/${name}`;
      }
    }
  });
</script>

前の例の {BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

ブート リソースの URL 以外のものをカスタマイズするには、loadBootResource 関数から fetch を直接呼び出して、結果を返すことができます。 次の例では、カスタム HTTP ヘッダーを送信要求に追加します。 既定の整合性チェックの動作を保持するため、integrity パラメーターを渡します。

Blazor Web アプリ:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        if (type == 'dotnetjs') {
          return null;
        } else {
          return fetch(defaultUri, {
            cache: 'no-cache',
            integrity: integrity,
            headers: { 'Custom-Header': 'Custom Value' }
          });
        }
      }
    }
  });
</script>

スタンドアロン Blazor WebAssembly:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      if (type == 'dotnetjs') {
        return null;
      } else {
        return fetch(defaultUri, {
          cache: 'no-cache',
          integrity: integrity,
          headers: { 'Custom-Header': 'Custom Value' }
        });
      }
    }
  });
</script>

前の例の {BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

loadBootResource 関数が null を返す場合、Blazor ではリソースの既定の読み込み動作が使用されます。 たとえば、dotnetjs ブート リソースは既定の読み込み動作を表す null または dotnetjs ブート リソースのソースの URI を返す必要があるため、上記のコードは dotnetjs ブート リソース (dotnet.*.js) に対して null を返します。

loadBootResource 関数では、Response Promise を返すこともできます。 例については、「ASP.NET Core Blazor WebAssembly のホストと展開」をご覧ください。

C# コードでヘッダーを制御する

C# コードで起動時にヘッダーを制御するには、次の方法を使用します。

次の例では、コンテンツ セキュリティ ポリシー (CSP) ヘッダーによって CSP がアプリに適用されます。 {POLICY STRING} プレースホルダーは、CSP ポリシーの文字列です。

サーバー側のシナリオとプリレンダリングされたクライアント側のシナリオ

ASP.NET Core ミドルウェアを使用してヘッダー コレクションを制御します。

Program ファイル:

Startup.csStartup.Configure で:

app.Use(async (context, next) =>
{
    context.Response.Headers.Append("Content-Security-Policy", "{POLICY STRING}");
    await next();
});

前の例ではインライン ミドルウェアを使用していますが、カスタム ミドルウェア クラスを作成し、Program ファイルで拡張メソッドを使用してミドルウェアを呼び出すこともできます。 詳細については、「カスタム ASP.NET Core ミドルウェアを記述する」を参照してください。

プリレンダリングなしのクライアント側の開発

OnPrepareResponse ステージでの応答ヘッダーを指定する StaticFileOptionsMapFallbackToFile に渡します。

サーバー側の Program ファイル:

Startup.csStartup.Configure で:

var staticFileOptions = new StaticFileOptions
{
    OnPrepareResponse = context =>
    {
        context.Context.Response.Headers.Append("Content-Security-Policy", 
            "{POLICY STRING}");
    }
};

...

app.MapFallbackToFile("index.html", staticFileOptions);

CSP について詳しくは、「ASP.NET Core Blazor のコンテンツ セキュリティ ポリシーを適用する」をご覧ください。

クライアント側の読み込みの進行状況インジケーター

読み込み進行状況インジケーターは、アプリの読み込みの進行状況をユーザーに対して表示するもので、アプリの読み込みが正常に進んでおり、ユーザーは読み込みが完了するまで待機する必要があることを示します。

Blazor Web アプリ読み込みの進行状況

Blazor WebAssembly アプリで使用される読み込み進行状況インジケーターは、Blazor Web アプリ プロジェクト テンプレートから作成されたアプリには存在しません。 通常、読み込み進行状況インジケーターは対話型の WebAssembly コンポーネントには望ましくありません。なぜなら、初期読み込み時間を短縮するために、Blazor Web Apps によってクライアント側コンポーネントがサーバー上でプリレンダリングされるためです。 混合レンダリング モードの状況では、フレームワークまたは開発者コードで次の問題を回避することに注意する必要もあります。

  • レンダリングされた同じページに複数の読み込みインジケーターを表示する。
  • WebAssembly ランタイムの読み込み中に、プリレンダリングされたコンテンツを誤って破棄する。

.NET の今後のリリースでは、フレームワークベースの読み込み進行状況インジケーターが提供される可能性があります。 それまでの間は、Blazor Web アプリにカスタムの読み込み進行状況インジケーターを追加できます。

.Client アプリ内に、OperatingSystem.IsBrowser を呼び出す LoadingProgress コンポーネントを作成します。

  • false の場合、Blazor バンドルのダウンロード中、Blazor ランタイムがクライアント上でアクティブ化されるまで、読み込み進行状況インジケーターを表示します。
  • true の場合、要求されたコンポーネントのコンテンツをレンダリングします。

次のデモでは、Blazor WebAssembly テンプレートから作成されたアプリ内にある読み込み進行状況インジケーターを使用しています (テンプレートに用意されているスタイルの変更を含みます)。 スタイルは、HeadContent コンポーネントによってアプリの <head> コンテンツに読み込まれます。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

LoadingProgress.razor:

@if (!OperatingSystem.IsBrowser())
{
    <HeadContent>
        <style>
            .loading-progress {
                position: relative;
                display: block;
                width: 8rem;
                height: 8rem;
                margin: 20vh auto 1rem auto;
            }

                .loading-progress circle {
                    fill: none;
                    stroke: #e0e0e0;
                    stroke-width: 0.6rem;
                    transform-origin: 50% 50%;
                    transform: rotate(-90deg);
                }

                    .loading-progress circle:last-child {
                        stroke: #1b6ec2;
                        stroke-dasharray: 
                            calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 
                            500%;
                        transition: stroke-dasharray 0.05s ease-in-out;
                    }

            .loading-progress-text {
                position: relative;
                text-align: center;
                font-weight: bold;
                top: -90px;
            }

                .loading-progress-text:after {
                    content: var(--blazor-load-percentage-text, "Loading");
                }

            code {
                color: #c02d76;
            }
        </style>
    </HeadContent>
    <svg class="loading-progress">
        <circle r="40%" cx="50%" cy="50%" />
        <circle r="40%" cx="50%" cy="50%" />
    </svg>
    <div class="loading-progress-text"></div>
}
else
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

対話型 WebAssembly レンダリングを採用するコンポーネントで、コンポーネントの Razor マークアップを LoadingProgress コンポーネントでラップします。 次の例は、Blazor Web アプリ プロジェクト テンプレートから作成されたアプリのCounter コンポーネントを使用したアプローチを示しています。

Pages/Counter.razor:

@page "/counter"
@rendermode InteractiveWebAssembly

<PageTitle>Counter</PageTitle>

<LoadingProgress>
    <h1>Counter</h1>

    <p role="status">Current count: @currentCount</p>

    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</LoadingProgress>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Blazor WebAssembly アプリ読み込みの進行状況

プロジェクト テンプレートには、スケーラブル ベクター グラフィックス (SVG) と、アプリの読み込みの進行状況を示すテキスト インジケーターが含まれています。

進行状況インジケーターは、Blazor で指定された次の 2 つの CSS カスタム プロパティ (変数) を使用して、HTML と CSS で実装されます。

  • --blazor-load-percentage: 読み込まれたアプリ ファイルの割合。
  • --blazor-load-percentage-text: 読み込まれたアプリ ファイルの割合。最も近い整数に四捨五入されます。

上記の CSS 変数を使用して、アプリのスタイルに一致するカスタム進行状況インジケーターを作成できます。

次に例を示します。

  • resourcesLoaded は、アプリの起動時に読み込まれたリソースのある時点でのカウントです。
  • totalResources は、読み込むリソースの合計数です。
const percentage = resourcesLoaded / totalResources * 100;
document.documentElement.style.setProperty(
  '--blazor-load-percentage', `${percentage}%`);
document.documentElement.style.setProperty(
  '--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`);

既定の円形進行状況インジケーターは、wwwroot/index.html ファイル内の HTML に実装されます。

<div id="app">
    <svg class="loading-progress">
        <circle r="40%" cx="50%" cy="50%" />
        <circle r="40%" cx="50%" cy="50%" />
    </svg>
    <div class="loading-progress-text"></div>
</div>

プロジェクト テンプレートのマークアップと既定の進行状況インジケーターのスタイルを確認するには、ASP.NET Core 参照ソースをご覧ください。

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

既定の円形進行状況インジケーターを使用する代わりに、次の例では線形進行状況インジケーターを実装する方法を示します。

wwwroot/css/app.css に次のスタイルを追加します。

.linear-progress {
    background: silver;
    width: 50vw;
    margin: 20% auto;
    height: 1rem;
    border-radius: 10rem;
    overflow: hidden;
    position: relative;
}

.linear-progress:after {
    content: '';
    position: absolute;
    inset: 0;
    background: blue;
    scale: var(--blazor-load-percentage, 0%) 100%;
    transform-origin: left top;
    transition: scale ease-out 0.5s;
}

CSS 変数 (var(...)) を使用して、--blazor-load-percentage の値を、アプリのファイルの読み込みの進行状況を示す青い擬似要素の scale プロパティに渡します。 アプリが読み込まれると、--blazor-load-percentage が自動的に更新され、進行状況インジケーターの視覚的表現が動的に変更されます。

wwwroot/index.html で、<div id="app">...</div> の既定の SVG 円形インジケーターを削除し、次のマークアップに置き換えます。

<div class="linear-progress"></div>

.NET WebAssembly ランタイムの構成

高度なプログラミング シナリオでは、 configureRuntime 関数を dotnet ランタイム ホスト ビルダーと共に使用して、.NET WebAssembly ランタイムを構成します。 たとえば、dotnet.withEnvironmentVariable は次の環境変数を設定します:

  • .NET WebAssembly ランタイムを構成します。
  • C ライブラリの動作を変更します。

configureRuntime 関数は、ブラウザ プロファイルとの統合を有効にするのにもしようできます。

環境変数を設定する次の例では:

  • {BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。
  • {NAME} プレースホルダーは環境変数の名前です。
  • {VALUE} プレースホルダーは環境変数の値です。

Blazor Web アプリ:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    webAssembly: {
      configureRuntime: dotnet => {
        dotnet.withEnvironmentVariable("{NAME}", "{VALUE}");
      }
    }
  });
</script>

スタンドアロン Blazor WebAssembly:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    configureRuntime: dotnet => {
      dotnet.withEnvironmentVariable("{NAME}", "{VALUE}");
    }
  });
</script>

Note

.NET ランタイム インスタンスには、Blazor WebAssembly ランタイム API (Blazor.runtime) を使用してアクセスできます。 たとえば、アプリのビルド構成は、Blazor.runtime.runtimeBuildInfo.buildConfiguration を使用して取得できます。

.NET WebAssembly ランタイム構成の詳細については、「dotnet/runtime GitHub リポジトリのランタイムの TypeScript 定義ファイル (dotnet.d.ts)」を参照してください。

Note

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

拡張ナビゲーションとフォーム処理を無効にする

"このセクションは Blazor WebAssembly に適用されます。"

拡張ナビゲーションとフォーム処理を無効にするには、Blazor.startdisableDomPreservationtrue に設定してください。

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    ssr: { disableDomPreservation: true }
  });
</script>

前の例の {BLAZOR SCRIPT} プレースホルダーは、Blazor スクリプトのパスとファイル名です。 スクリプトの場所については、「ASP.NET Core Blazor プロジェクトの構造」を参照してください。

その他のリソース