ASP.NET Core Blazor のホストと展開

注意

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

警告

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

この記事では、Blazor アプリをホストおよび展開する方法について説明します。

アプリの発行

アプリは、リリース構成での展開のために発行されます。

Note

Server プロジェクトからホステッド Blazor WebAssembly ソリューションを発行します。

  1. [ビルド] メニューから 「{APPLICATION} を発行する] コマンドを選択します。{APPLICATION} プレースホルダーはアプリの名前です。
  2. [publish target]\(発行先\) を選択します。 ローカルに発行するには、[フォルダー] を選択します。
  3. [フォルダーの選択] フィールド内で既定の場所を受け入れるか、または別の場所を指定します。 Publish ボタンを選択します。

アプリを発行すると、プロジェクトの依存関係の復元がトリガーされ、展開されるアセットを作成する前にプロジェクトがビルドされます。 ビルド プロセスの一環として、アプリのダウンロード サイズを縮小し読み込み時間を短縮するため、未使用のメソッドおよびアセンブリが削除されます。

発行場所:

  • Blazor Web App: アプリは /bin/Release/{TARGET FRAMEWORK}/publish フォルダーに発行されます。 publish フォルダーの内容をホストに展開します。
  • Blazor WebAssembly: アプリは bin\Release\net8.0\browser-wasm\publish\ フォルダーに発行されます。 アプリを静的サイトとして展開するには、wwwroot フォルダーの内容を静的サイトのホストにコピーします。
  • Blazor Server: アプリは /bin/Release/{TARGET FRAMEWORK}/publish フォルダーに発行されます。 publish フォルダーの内容をホストに展開します。
  • Blazor WebAssembly
    • スタンドアロン: アプリは、アプリの発行に使用される SDK のバージョンに応じて、/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot または bin\Release\{TARGET FRAMEWORK}\browser-wasm\publish フォルダーに発行されます。 アプリを静的サイトとして展開するには、wwwroot フォルダーの内容を静的サイトのホストにコピーします。
    • ホステッド: クライアントの Blazor WebAssembly アプリは、クライアント アプリの他の静的な Web アセットと共に、サーバー アプリの /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot フォルダーに発行されます。 publish フォルダーの内容をホストに展開します。

上記のパスの {TARGET FRAMEWORK} は、ターゲット フレームワーク (たとえば、net8.0) です。

IIS

IIS で Blazor アプリをホストするには、次のリソースを参照してください。

Blazor アプリを含め、ASP.NET Core アプリ間のアプリ プールの共有はサポートされていません。 IIS でホストする場合は、アプリごとに 1 つのアプリ プールを使い、複数のアプリをホストするために IIS の仮想ディレクトリを使用しないようにしてください。

"1 つ" のアプリ プールに対して、ASP.NET Core アプリによってホストされる 1 つ以上の Blazor WebAssembly アプリ (ホステッド Blazor WebAssembly ソリューションと呼ばれます) がサポートされます。 ただし、1 つのアプリ プールを複数のホステッド Blazor WebAssembly ソリューションに割り当てること、またはサブアプリのホスティング シナリオで割り当てることは推奨されず、またサポートもされません。

ソリューションの詳細については、「ASP.NET Core Blazor 用のツール」を参照してください。

アプリのベース パス

アプリのベース パスとは、アプリのルート URL パスのことです。 Blazor アプリでルーティングが成功するためには、既定のアプリ ベース パス / にないルート URL パスに対するフレームワーク構成が必要です。

次の ASP.NET Core アプリと Blazor サブアプリについて考えてみましょう。

  • ASP.NET Core アプリは MyApp と命名します。
    • このアプリは、物理的に d:/MyApp に存在します。
    • 要求は、https://www.contoso.com/{MYAPP RESOURCE} で受信されます。
  • CoolApp という名前の Blazor アプリは MyApp のサブアプリです。
    • このサブアプリは、物理的に d:/MyApp/CoolApp に存在します。
    • 要求は、https://www.contoso.com/CoolApp/{COOLAPP RESOURCE} で受信されます。

CoolApp に対して構成を追加指定しない場合、このシナリオではサブ アプリにはそれがサーバー上のどこの場所にあるかわかりません。 たとえば、相対 URL パス /CoolApp/ にあることがわからない場合、アプリはそのリソースに対する正しい相対 URL を作成できません。 このシナリオは、アプリがルート URL パスでホストされていない場合、さまざまなホスティングおよびリバース プロキシのシナリオでも適用されます。

背景

アンカー タグの宛先 (href) は、次の 2 つのエンドポイントのいずれかで構成できます。

  • 絶対位置。スキーム (省略した場合はページのスキームが既定値になります)、ホスト、ポート、およびパスまたはスラッシュ (/) の後に続くパスが含まれます。

    例: https://example.com/a/b/c または /a/b/c

  • 相対位置。パスのみが含まれており、スラッシュ (/) で始まりません。 これらは、現在のドキュメント URL または <base> タグの値 (指定されている場合) を基準にして解決されます。

    例: a/b/c

構成されたアプリのベース パスの末尾にスラッシュ (/) が存在することは、アプリの URL のベース パスを計算する上で重要です。 たとえば、 https://example.com/a のベース パスは https://example.com/ であり、末尾にスラッシュがある https://example.com/a/ のベース パスは https://example.com/a となります。

ASP.NET Core アプリの Blazor に関連するリンクには、次の 3 つのソースがあります。

  • 通常、Razor コンポーネント (.razor) の URL は相対的です。
  • Blazor スクリプト (blazor.*.js) などのスクリプトの URL。ドキュメントに対して相対的です。
  • _Host.cshtml ファイル (Blazor Server) に手動で記述された URL。異なるドキュメント内でレンダリングする場合は、常に絶対 URL にする必要があります。
  • 通常、Razor コンポーネント (.razor) の URL は相対的です。
  • Blazor スクリプト (blazor.*.js) などのスクリプトの URL。ドキュメントに対して相対的です。

異なるドキュメント (/Admin/B/C//Admin/D/E/ など) から Blazor アプリをレンダリングする場合は、アプリのベース パスを考慮する必要があります。ベース パスが異なると、アプリが各ドキュメントでレンダリングされる際にリソースが間違った URL からフェッチされることになります。

相対リンクを正しく解決するという課題に対処するには、次の 2 つの方法があります。

  • ルートとしてレンダリングされたドキュメントを使用して、リソースを動的にマップします。
  • ドキュメントの一貫したベース パスを設定し、そのベース パスの下にリソースをマップします。

最初のオプションはドキュメントごとにナビゲーションが異なるため、より複雑であり、最も一般的なアプローチではありません。 ページ /Something/Else をレンダリングする例を次に示します。

  • /Admin/B/C/ の下にレンダリングすると、ページは /Admin/B/C/Something/Else のパスでレンダリングされます。
  • /Admin/D/E/ の下にレンダリングすると、ページは同じパス/Admin/B/C/Something/Else でレンダリングされます。

最初のアプローチでは、ルーティングによって IDynamicEndpointMetadataMatcherPolicy が提供されます。これらは組み合わせることで、実行時にリクエストのルーティング方法を決定する完全に動的なソリューションを実装するための基礎となります。

通常の方法である 2 番目のオプションでは、アプリはドキュメント内のベース パスを設定し、サーバー エンドポイントをベースの下のパスにマップします。 次のガイダンスでは、このアプローチを採用しています。

サーバー側 Blazor

Program ファイル内の MapBlazorHub へのパスを渡して、サーバー側 Blazor アプリの SignalR ハブをマップします。

app.MapBlazorHub("base/path");

MapBlazorHub を使用する利点は、具体的なパスだけでなく、"{tenant}" などのパターンをマップできることです。

また、アプリが分岐ミドルウェア パイプラインを持つ仮想フォルダー内にある場合に SignalR ハブをマップすることもできます。 次の例では、/base/path/ への要求は Blazor の SignalR ハブによって処理されます。

app.Map("/base/path/", subapp => {
    subapp.UsePathBase("/base/path/");
    subapp.UseRouting();
    subapp.UseEndpoints(endpoints => endpoints.MapBlazorHub());
});

アプリのベース パスを構成する」セクションのガイダンスに従って、<base> タグを構成します。

ホステッド Blazor WebAssembly

ホストされている Blazor WebAssembly アプリの場合:

  • Server プロジェクト (Program.cs) の場合:
    • UseBlazorFrameworkFiles のパスを調整します (たとえば、app.UseBlazorFrameworkFiles("/base/path");)。
    • UseStaticFiles への呼び出しを構成します (たとえば、app.UseStaticFiles("/base/path");)。
  • Client プロジェクトの場合:
    • 静的 Web アセットを提供するためのパスと一致するように、プロジェクト ファイル内の <StaticWebAssetBasePath> を構成します (たとえば、<StaticWebAssetBasePath>base/path</StaticWebAssetBasePath> )。
    • アプリのベース パスを構成する」セクションのガイダンスに従って、<base> タグを構成します。

ホストされた Blazor WebAssembly ソリューションで複数の Blazor WebAssembly アプリをホストする例については、「複数のホストされた ASP.NET Core Blazor WebAssembly アプリ」を参照してください。このページでは、複数の Blazor WebAssembly クライアント アプリのドメイン/ポート ホスティングとサブパス ホスティングに関するアプローチについて説明しています。

スタンドアロン Blazor WebAssembly

スタンドアロン Blazor WebAssembly アプリの場合は、「アプリのベース パスを構成する」セクションのガイダンスに従って、<base> タグのみを構成します。

アプリのベース パスを構成する

Blazor アプリのベース パスのhttps://www.contoso.com/CoolApp/の構成を提供するには、app ベース パス (<base>) (相対ルート パスとも呼ばれます) を設定します。

アプリのベース パスを構成することにより、ルート ディレクトリに存在しないコンポーネントでアプリのルート パスへの相対 URL を構築できます。 ディレクトリ構造の別のレベルに存在するコンポーネントが、アプリ内のさまざまな場所にある他のリソースに対するリンクを構築できます。 アプリのベース パスは、リンクの href ターゲットがアプリのベース パス URI 空間内にある、選択されたハイパーリンクの阻止にも使用されます。 内部のナビゲーションは、Router コンポーネントによって処理されます。

<link>要素のhref属性など、URL である属性値を持つ要素の前に、<base> タグを<head>マークアップ ( <head> コンテンツの割り当て) に配置します。

多くのホスティング シナリオでは、アプリへの相対 URL パスは、アプリのルートです。 このような既定のケースでは、アプリの相対 URL ベース パスは、/ であり、<head> コンテンツ<base href="/" /> として構成されます。

多くのホスティング シナリオでは、アプリへの相対 URL パスは、アプリのルートです。 これらの既定のケースでは、アプリの相対 URL のベース パスは、<head> コンテンツ で次のようになります。

  • Blazor Server: ~/<base href="~/" /> として構成。
  • Blazor WebAssembly: /<base href="/" /> として構成。

Note

GitHub ページと IIS サブアプリなど、一部のホスティング シナリオの場合、アプリのベースパスは、アプリへのサーバーの相対 URL パスに設定する必要があります。

  • サーバー側 Blazor アプリでは、次の "いずれか" の方法を使用してください。

    • オプション 1: <base> タグを使用して、アプリのベース パスを設定する (<head> コンテンツの場所)。

      <base href="/CoolApp/">
      

      末尾にスラッシュが必要です。

    • オプション 2: WebApplicationBuilder がビルド (builder.Build()) された直後に、アプリの要求処理パイプライン (Program.cs) で "最初に" UsePathBase を呼び出して、要求パスと対話する以降のミドルウェアのベース パスを構成します。

      app.UsePathBase("/CoolApp");
      

      UsePathBase の呼び出しは、Blazor Server アプリをローカル環境でも実行したい場合に推奨されます。 たとえば、Properties/launchSettings.json に起動 URL を指定します。

      "launchUrl": "https://localhost:{PORT}/CoolApp",
      

      前の例の {PORT} プレース ホルダーは、applicationUrl 構成パス内のセキュリティで保護されたポートと一致するポートです。 次の例では、ポート 7279 におけるアプリの完全起動プロファイルを示しています。

      "BlazorSample": {
        "commandName": "Project",
        "dotnetRunMessages": true,
        "launchBrowser": true,
        "applicationUrl": "https://localhost:7279;http://localhost:5279",
        "launchUrl": "https://localhost:7279/CoolApp",
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
      }
      

      launchSettings.json ファイルの詳細については、「ASP.NET Core で複数の環境を使用する」を参照してください。 Blazor アプリのベース パスとホスティングの詳細については、 「Blazor MVC 統合の <base href="/" /> またはベース タグの代替方法 (dotnet/aspnetcore #43191)」を参照してください。

  • スタンドアロン Blazor WebAssembly (wwwroot/index.html):

    <base href="/CoolApp/">
    

    末尾にスラッシュが必要です。

  • ホステッド Blazor WebAssembly (Client プロジェクト、wwwroot/index.html):

    <base href="/CoolApp/">
    

    末尾にスラッシュが必要です。

    Server プロジェクトで、WebApplicationBuilder がビルド (builder.Build()) された直後に、アプリの要求処理パイプライン (Program.cs) で "最初に" UsePathBase を呼び出して、要求パスと対話する以降のミドルウェアのベース パスを構成します。

    app.UsePathBase("/CoolApp");
    

Note

WebApplication を使用する場合 (ASP.NET Core 5.0 から 6.0 への移行に関する記事を参照) は、UsePathBase の後に app.UseRouting を呼び出して、ルーティング ミドルウェアがルートを照合する前に変更されたパスを確認できるようにする必要があります。 そうしない場合、ミドルウェアの順序ルーティングに関する記事で説明されているように、ルートはパスが書き直される前に UsePathBase によって照合されます。

アプリ全体のリンクの先頭にフォワード スラッシュを付けないでください。 パス セグメント区切り記号を使わないか、ドットスラッシュ (./) による相対パス表記を使ってください。

  • 正しくない: <a href="/account">
  • 正しい: <a href="account">
  • 正しい: <a href="./account">

HttpClient サービスを使用する Blazor WebAssembly Web API 要求では、JSON ヘルパー (HttpClientJsonExtensions) によって URL の先頭にフォワード スラッシュ (/) が付けられていないことを確認します。

  • 正しくない: var rsp = await client.GetFromJsonAsync("/api/Account");
  • 正しい: var rsp = await client.GetFromJsonAsync("api/Account");

Navigation Manager の相対リンクの先頭にフォワード スラッシュを付けないでください。 パスのセグメント区切り記号を使わないか、ドットスラッシュ (./) による相対パス表記を使ってください (Navigation は挿入された NavigationManager です):

  • 正しくない: Navigation.NavigateTo("/other");
  • 正しい: Navigation.NavigateTo("other");
  • 正しい: Navigation.NavigateTo("./other");

Azure または IIS ホスティングの一般的な構成では、通常、追加の構成は必要ありません。 IIS 以外のホスティングおよびリバース プロキシ ホスティングの一部のシナリオでは、追加の静的ファイル ミドルウェア構成が必要になる場合があります。

  • 静的ファイルを正しく処理する場合 (たとえば、app.UseStaticFiles("/CoolApp");)。
  • Blazor スクリプトを提供する場合 (_framework/blazor.*.js)。 詳しくは、「ASP.NET Core Blazor の静的ファイル」をご覧ください。

ルート以外の相対 URL パスが構成されている Blazor WebAssembly アプリの場合 (例: <base href="/CoolApp/">)、そのアプリは "ローカルで実行されると" 自身のリソースを見つけることができません。 ローカルでの開発およびテスト中は、実行時の <base> タグの href 値と一致するパス ベース引数を指定することで、この問題を克服することができます。 末尾にはスラッシュを含めないでください。 アプリをローカルで実行する際にパス ベース引数を渡すには、以下のようにアプリのディレクトリから --pathbase オプションを指定して dotnet watch (または dotnet run) コマンドを実行します。

dotnet watch --pathbase=/{RELATIVE URL PATH (no trailing slash)}

相対 URL パスが /CoolApp/ (<base href="/CoolApp/">) の Blazor WebAssembly アプリについては、このコマンドは次のようになります。

dotnet watch --pathbase=/CoolApp

dotnet watch (または dotnet run) を使用して手動で指定するのではなく、pathbase を自動的に指定するようにアプリの起動プロファイルを構成したい場合は、Properties/launchSettings.jsoncommandLineArgs プロパティを設定します。 次も、起動 URL (launchUrl) を構成します。

"commandLineArgs": "--pathbase=/{RELATIVE URL PATH (no trailing slash)}",
"launchUrl": "{RELATIVE URL PATH (no trailing slash)}",

例のように CoolApp を使用します。

"commandLineArgs": "--pathbase=/CoolApp",
"launchUrl": "CoolApp",

--pathbase オプションを指定した dotnet watch (または dotnet run)、あるいはベース パスを設定する起動プロファイル構成を使用すると、Blazor WebAssembly アプリは http://localhost:port/CoolApp でローカルに応答します。

launchSettings.json ファイルの詳細については、「ASP.NET Core で複数の環境を使用する」を参照してください。 Blazor アプリのベース パスとホスティングの詳細については、 「Blazor MVC 統合の <base href="/" /> またはベース タグの代替方法 (dotnet/aspnetcore #43191)」を参照してください。

構成からアプリのベース パスを取得する

次のガイダンスでは、さまざまな環境のアプリ設定ファイルから <base> タグのパスを取得する方法について説明します。

アプリ設定ファイルをアプリに追加します。 次の例は、Staging 環境 (appsettings.Staging.json) の場合です。

{
  "AppBasePath": "staging/"
}

サーバー側の Blazor アプリで、<head> コンテンツの構成からベース パスを読み込みます。

@inject IConfiguration Config

...

<head>
    ...
    <base href="/@(Config.GetValue<string>("AppBasePath"))" />
    ...
</head>

または、サーバー側アプリは、UsePathBase の構成から値を取得できます。 WebApplicationBuilder が構築された (builder.Build()) 直後に、次のコードをアプリの要求処理パイプライン (Program.cs) の最初に配置します。 次の例では、構成キー AppBasePath を使います。

app.UsePathBase($"/{app.Configuration.GetValue<string>("AppBasePath")}");

クライアントサイド Blazor WebAssembly アプリ内は以下のようになっています。:

  • wwwroot/index.html から <base> タグを削除します。

    - <base href="..." />
    
  • App コンポーネント (App.razor) の HeadContent コンポーネントを介してアプリのベース パスを指定します。

    @inject IConfiguration Config
    
    ...
    
    <HeadContent>
        <base href="/@(Config.GetValue<string>("AppBasePath"))" />
    </HeadContent>
    

非ステージング環境など、読み込む構成値がない場合、上記の href はルート パス / に解決されます。

このセクションの例では、アプリ設定からアプリのベース パスを指定することに焦点を当てていますが、IConfiguration からパスを読み取るアプローチは、どの構成プロバイダーでも有効です。 詳細については、次のリソースを参照してください。

Blazor ServerMapFallbackToPage 構成

"このセクションは Blazor Server アプリにのみ適用されます。 " MapFallbackToPage は、Blazor Web App および Blazor WebAssembly アプリではサポートされていません。

アプリでカスタム リソースと Razor コンポーネントを含む区分が別に必要なシナリオでは、次の操作を行います。

  • アプリの Pages フォルダー内に、リソースを保持するためのフォルダーを作成します。 たとえば、アプリの管理者セクションは、Admin という名前の新しいフォルダー内に作成されます (Pages/Admin)。

  • その区分のルート ページ (_Host.cshtml) を作成します。 たとえば、アプリのメイン ルート ページ (Pages/_Host.cshtml) から Pages/Admin/_Host.cshtml ファイルを作成します。 Admin _Host ページには、@page ディレクティブを指定しないでください。

  • 区分のフォルダーにレイアウトを追加します (例: Pages/Admin/_Layout.razor)。 別の区分のレイアウトで、<base> タグ href を設定して、その区分のフォルダーと一致するようします (例: <base href="/Admin/" />)。 デモンストレーションの目的で、ページ内の静的リソースに ~/ を追加します。 次に例を示します。

    • ~/css/bootstrap/bootstrap.min.css
    • ~/css/site.css
    • ~/BlazorSample.styles.css (サンプル アプリの名前空間は BlazorSample です)。
    • ~/_framework/blazor.server.js (Blazor スクリプト)
  • 区分に独自の静的アセット フォルダーが必要な場合は、該当するフォルダーを追加し、その場所を Program.cs 内の静的ファイル ミドルウェアに指定します (例: app.UseStaticFiles("/Admin/wwwroot"))。

  • Razor コンポーネントが区分のフォルダーに追加されます。 少なくとも、区分の正しい @page ディレクティブを使用して Index コンポーネントを区分フォルダーに追加します。 たとえば、アプリの既定の Pages/Index.razor のファイルに基づいて Pages/Admin/Index.razor ファイルを追加します。 ファイルの先頭にルート テンプレートとして Admin 区分を指定します (@page "/admin")。 必要に応じて追加のコンポーネントを追加します。 たとえば、@page "/admin/component1@page ディレクティブとルート テンプレートを使用した Pages/Admin/Component1.razor

  • Program.cs では、_Host ページへのフォールバック ルート ページ パスの直前に、区分の要求パスに対して MapFallbackToPage を呼び出します。

    ...
    app.UseRouting();
    
    app.MapBlazorHub();
    app.MapFallbackToPage("~/Admin/{*clientroutes:nonfile}", "/Admin/_Host");
    app.MapFallbackToPage("/_Host");
    
    app.Run();
    

複数のBlazor WebAssembly アプリをホストする

ホステッド Blazor ソリューションで複数の Blazor WebAssembly アプリをホストする方法の詳細については、「複数のホステッド ASP.NET Core Blazor WebAssembly アプリ」を参照してください。

展開

展開のガイダンスについては、次のトピックを参照してください。