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

注意

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

重要

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

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

この記事では、ASP.NET Core、Content Delivery Network (CDN)、ファイル サーバー、GitHub ページを使用して、Blazor WebAssembly をホストしデプロイする方法について説明します。

Blazor WebAssembly ホスティング モデルを使用する場合は以下のようになります。

  • Blazor アプリ、その依存関係、.NET ランタイムが並行してブラウザーにダウンロードされます。
  • アプリがブラウザー UI スレッド上で直接実行されます。

この記事は、Blazor アプリが静的ホスティング Web サーバーまたはサービスに配置されるデプロイ シナリオに関するものです。.NET は Blazor アプリの提供には使用されません。 この戦略については、「スタンドアロン展開」セクションで示されます。これには、Blazor WebAssembly アプリを IIS サブアプリとしてホストする方法についての情報が含まれています。

次の展開戦略がサポートされています。

  • Blazor アプリは、ASP.NET Core アプリによって提供されます。 この戦略については、「ASP.NET Core でのホストされた展開」セクションで説明します。
  • Blazor アプリは、Blazor アプリの提供に .NET が使用されていない静的ホスティング Web サーバーまたはサービス上に配置されます。 この戦略については、「スタンドアロン展開」セクションで示されます。これには、Blazor WebAssembly アプリを IIS サブアプリとしてホストする方法についての情報が含まれています。
  • ASP.NET Core アプリは、複数の Blazor WebAssembly アプリをホストします。 詳細については、「複数のホストされた ASP.NET Core Blazor WebAssembly アプリ」を参照してください。

.NET アセンブリの Webcil パッケージ形式

Webcil は、制限の厳しいネットワーク環境で Blazor WebAssembly を使用できるように設計された、.NET アセンブリの Web 対応パッケージ形式です。 Webcil ファイルでは標準の WebAssembly ラッパーが使われます。アセンブリは、標準の .wasm ファイル拡張子を使用する WebAssembly ファイルとして配置されます。

Webcil は、Blazor WebAssembly アプリを公開するときの既定のパッケージ形式です。 Webcil の使用を無効にするには、アプリのプロジェクト ファイルで次の MS Build プロパティを設定します。

<PropertyGroup>
  <WasmEnableWebcil>false</WasmEnableWebcil>
</PropertyGroup>

Ahead-Of-Time (AOT) コンパイル

Blazor WebAssembly では、Ahead-Of-Time (AOT) コンパイルがサポートされています。これにより、.NET コードを直接 WebAssembly にコンパイルできます。 AOT コンパイルを使用すると、アプリのサイズが大きくなりますが、実行時のパフォーマンスが向上します。

AOT コンパイルが有効にされていない場合、Blazor WebAssembly アプリは WebAssembly に実装された .NET 中間言語 (IL) インタープリターを使ってブラウザー上で実行され、部分的に Just-In-Time (JIT) ランタイムがサポートされます (非公式には Jiterpreter と呼ばれます)。 .NET IL コードは解釈されるため、通常、アプリが実行される速度は、IL の解釈がないサーバー側の .NET JIT ランタイムの場合より遅くなります。 AOT コンパイルでは、アプリの .NET コードを WebAssembly に直接コンパイルし、ブラウザーによるネイティブ WebAssembly 実行ができるようにすることで、このパフォーマンスの問題に対処します。 AOT のパフォーマンスを向上すれば、CPU が集中的に使用されるタスクを実行するアプリの機能を大幅に強化することができます。 AOT コンパイルを使用する場合の欠点としては、AOT でコンパイルされたアプリは、一般に、IL で解釈される場合よりもサイズが大きくなるため、最初に要求されたときに、通常、クライアントへのダウンロードに時間がかかるということがあります。

AOT コンパイルが有効にされていない場合、Blazor WebAssembly アプリは WebAssembly に実装された .NET 中間言語 (IL) インタープリターを使ってブラウザー上で実行されます。 .NET コードは解釈されるため、通常、アプリが実行される速度は、サーバー側の .NET Just-In-Time (JIT) ランタイムの場合より遅くなります。 AOT コンパイルでは、アプリの .NET コードを WebAssembly に直接コンパイルし、ブラウザーによるネイティブ WebAssembly 実行ができるようにすることで、このパフォーマンスの問題に対処します。 AOT のパフォーマンスを向上すれば、CPU が集中的に使用されるタスクを実行するアプリの機能を大幅に強化することができます。 AOT コンパイルを使用する場合の欠点としては、AOT でコンパイルされたアプリは、一般に、IL で解釈される場合よりもサイズが大きくなるため、最初に要求されたときに、通常、クライアントへのダウンロードに時間がかかるということがあります。

.NET WebAssembly ビルド ツールのインストールに関するガイダンスについては、「ASP.NET Core Blazor 用のツール」をご覧ください。

WebAssembly AOT コンパイルを有効にするには、true に設定された <RunAOTCompilation> プロパティを Blazor WebAssembly アプリのプロジェクト ファイルに追加します。

<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>

アプリを WebAssembly にコンパイルするには、アプリを発行します。 Release 構成を発行すると、.NET 中間言語 (IL) リンクも実行されて、発行されたアプリのサイズが確実に縮小されます。

dotnet publish -c Release

WebAssembly の AOT のコンパイルは、プロジェクトが発行されたときにのみ実行されます。 プロジェクトが開発中 (Development環境) に実行される場合、AOT コンパイルは通常使用されません。これは、AOT コンパイルは通常、小さなプロジェクトでは数分かかり、大きなプロジェクトでは大幅に長くかかる可能性があるためです。 ASP.NET Core の将来のリリースで AOT コンパイルのビルド時間の短縮を実現できるように、開発に取り組んでいます。

AOT でコンパイルされた Blazor WebAssembly アプリのサイズは、通常、.NET IL にコンパイルされた場合のアプリのサイズよりも大きくなります。

  • サイズの違いはアプリに依存しますが、AOT でコンパイルされたアプリのほとんどは、IL コンパイルされたバージョンの約 2 倍のサイズになります。 これは、AOT コンパイルを使用すると、実行時のパフォーマンス向上のために読み込み時間のパフォーマンスが低下することを意味します。 このようなトレードオフがあっても AOT コンパイルを使用する価値があるかどうかは、アプリによって異なります。 CPU を集中的に使用する Blazor WebAssembly アプリは、通常、AOT コンパイルから最も恩恵を受けます。

  • AOT でコンパイルされたアプリのサイズが大きくなるのは、次の 2 つのことのためです。

    • ネイティブ WebAssembly で高レベルの .NET IL 命令を表すには、より多くのコードが必要です。
    • アプリが発行されるとき、AOT ではマネージド DLL がトリミング "されません"。 Blazor では、リフレクション メタデータ用に、および特定の .NET ランタイム機能をサポートするために、DLL が必要です。 クライアントで DLL が必要であるためにダウンロード サイズは増加しますが、.NET エクスペリエンスとの互換性は高くなります。

Note

Mono/WebAssembly MSBuild のプロパティとターゲットについては、WasmApp.Common.targets (dotnet/runtime GitHub リポジトリ) を参照してください。 一般的な MSBuild プロパティに関する公式ドキュメントの提供は、ドキュメント blazor msbuild 構成オプション (dotnet/docs #27395) によって計画されています。

Ahead-Of-Time (AOT) コンパイル後に .NET IL をトリミングする

WasmStripILAfterAOT MSBuild オプションを使用すると、WebAssembly への AOT コンパイルの実行後、コンパイルされたメソッドの .NET Intermediate Language (IL) を削除できます。これにより、_framework フォルダーのサイズが小さくなります。

アプリのプロジェクト ファイル内で:

<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
  <WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup>

この設定は、ほとんどのコンパイルされたメソッド (ライブラリのメソッドやアプリ内のメソッドを含む) の IL コードをトリミングしてなくします。 コンパイルされたメソッドの一部は実行時に .NET インタープリターによって引き続き必要とされるため、すべてのコンパイルされたメソッドをトリミングできるわけではありません。

トリミング オプションに関する問題を報告するには、dotnet/runtime GitHub リポジトリで issue を作成します。

アプリが正常に実行されなくなる場合は、トリミング プロパティを無効にします。

<WasmStripILAfterAOT>false</WasmStripILAfterAOT>

一部のモバイル デバイス ブラウザーの最大ヒープ サイズを小さくする

クライアント (Blazor Web アプリまたはスタンドアロン Blazor WebAssembly アプリの .Client プロジェクト) で実行され、モバイル デバイス ブラウザー (特に iOS 上の Safari) を対象とする Blazor アプリをビルドする場合は、MSBuild プロパティ EmccMaximumHeapSize を使用してアプリの最大メモリを減らす必要があります。 既定値は 2,147,483,648 バイトで、サイズが大きすぎる可能性があり、ブラウザーが許可できない状態でアプリがさらにメモリを割り当てようとすると、アプリがクラッシュする可能性があります。 次の例では、Program ファイルで値を 268,435,456 バイトに設定します。

モバイル デバイス ブラウザー (特に iOS 上の Safari) を対象とする Blazor WebAssembly アプリをビルドする場合は、MSBuild プロパティ EmccMaximumHeapSize を使用してアプリの最大メモリを減らす必要があります。 既定値は 2,147,483,648 バイトで、サイズが大きすぎる可能性があり、ブラウザーが許可できない状態でアプリがさらにメモリを割り当てようとすると、アプリがクラッシュする可能性があります。 次の例では、Program ファイルで値を 268,435,456 バイトに設定します。

<EmccMaximumHeapSize>268435456</EmccMaximumHeapSize>

Mono/WebAssembly MSBuild プロパティとターゲットについて詳しくは、WasmApp.Common.targets (dotnet/runtime GitHub リポジトリ) をご覧ください。

ランタイムの再リンク

Blazor WebAssembly アプリの最大部分の 1 つは、WebAssembly ベースの .NET ランタイム (dotnet.wasm) です。これは、このアプリがユーザーのブラウザーから最初にアクセスされたときに、ブラウザーによってダウンロードされる必要があります。 .NET WebAssembly ランタイムを再リンクすると、未使用のランタイム コードが削除されるため、ダウンロード速度が向上します。

ランタイムの再リンクには、.NET の WebAssembly ビルド ツールをインストールする必要があります。 詳しくは、「ASP.NET Core Blazor 用のツール」をご覧ください。

.NET WebAssembly ビルド ツールをインストールすると、ランタイムの再リンクは、アプリが Release 構成で公開されるときに自動的に実行されます。 サイズは、グローバリゼーションを無効にしたときに、特に大きく縮小します。 詳しくは、「ASP.NET Core Blazor のグローバリゼーションおよびローカライズ」をご覧ください。

重要

ランタイムの再リンクの場合、JavaScript で呼び出し可能なクラス インスタンス .NET メソッドは、保護されていない限り、トリミングされます。 詳細については、「ASP.NET Core Blazor で JavaScript 関数から .NET メソッドを呼び出す」を参照してください。

ブート リソースの読み込み方法をカスタマイズする

loadBootResource API を使用してブート リソースの読み込み方法をカスタマイズします。 詳しくは、「ASP.NET Core Blazor の起動」をご覧ください。

[圧縮]

Blazor WebAssembly アプリが公開されると、公開中に出力が静的に圧縮されてアプリのサイズが縮小され、実行時の圧縮に必要なオーバーヘッドがなくなります。 次の圧縮アルゴリズムが使用されます。

Blazor は、適切な圧縮ファイルにサービスを提供するため、ホストに依存します。 Blazor WebAssembly スタンドアロン アプリをホストするとき、静的に圧縮されたファイルにサービスが提供されるよう、追加の作業が必要になることがあります。

Blazor は、適切な圧縮ファイルにサービスを提供するため、ホストに依存します。 ASP.NET Core でホストされたBlazor WebAssembly プロジェクトを使うときは、ホスト プロジェクトで、コンテンツ ネゴシエーションを実行したり、静的に圧縮されたファイルにサービスを提供したりできます。 Blazor WebAssembly スタンドアロン アプリをホストするとき、静的に圧縮されたファイルにサービスが提供されるよう、追加の作業が必要になることがあります。

  • IIS の web.config の圧縮構成については、IIS の「Brotli と Gzip の圧縮」セクションを参照してください。
  • 静的に圧縮されたファイル コンテント ネゴシエーションをサポートしない静的ホスティング ソリューションでホストする場合は、Brotli 圧縮ファイルをフェッチしてデコードするようにアプリを構成することを検討してください。

google/brotli GitHub リポジトリから、JavaScript Brotli デコーダーを入手します。 縮小されたデコーダー ファイルは、decode.min.js という名前で、リポジトリの js フォルダーにあります。

Note

decode.js スクリプトの縮小版 (decode.min.js) が失敗した場合は、代わりに縮小されていないバージョン (decode.js) を使用してください。

そのデコーダーを使用するようにアプリを更新します。

wwwroot/index.html ファイルで、Blazor の <script> タグで autostartfalse に設定します。

<script src="_framework/blazor.webassembly.js" autostart="false"></script>

Blazor の <script> タグの後、</body> 終了タグの前に、次の JavaScript コード <script> ブロックを追加してください。

Blazor Web アプリ:

<script type="module">
  import { BrotliDecode } from './decode.min.js';
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration' && type !== 'manifest') {
          return (async function () {
            const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
            if (!response.ok) {
              throw new Error(response.statusText);
            }
            const originalResponseBuffer = await response.arrayBuffer();
            const originalResponseArray = new Int8Array(originalResponseBuffer);
            const decompressedResponseArray = BrotliDecode(originalResponseArray);
            const contentType = type === 
              'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
            return new Response(decompressedResponseArray, 
              { headers: { 'content-type': contentType } });
          })();
        }
      }
    }
  });
</script>

スタンドアロン Blazor WebAssembly:

<script type="module">
  import { BrotliDecode } from './decode.min.js';
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration') {
        return (async function () {
          const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
          if (!response.ok) {
            throw new Error(response.statusText);
          }
          const originalResponseBuffer = await response.arrayBuffer();
          const originalResponseArray = new Int8Array(originalResponseBuffer);
          const decompressedResponseArray = BrotliDecode(originalResponseArray);
          const contentType = type === 
            'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
          return new Response(decompressedResponseArray, 
            { headers: { 'content-type': contentType } });
        })();
      }
    }
  });
</script>

ブート リソースの読み込みについて詳しくは、「ASP.NET Core Blazor の起動」をご覧ください。

圧縮を無効にするには、アプリケーションのプロジェクト ファイルに CompressionEnabled MSBuild プロパティを追加し、値を false に設定します。

<PropertyGroup>
  <CompressionEnabled>false</CompressionEnabled>
</PropertyGroup>

CompressionEnabled プロパティは、コマンド シェルで次の構文を使用して dotnet publish コマンドに渡すことができます。

dotnet publish -p:CompressionEnabled=false

圧縮を無効にするには、アプリケーションのプロジェクト ファイルに BlazorEnableCompression MSBuild プロパティを追加し、値を false に設定します。

<PropertyGroup>
  <BlazorEnableCompression>false</BlazorEnableCompression>
</PropertyGroup>

BlazorEnableCompression プロパティは、コマンド シェルで次の構文を使用して dotnet publish コマンドに渡すことができます。

dotnet publish -p:BlazorEnableCompression=false

正しいルーティングのために URL を書き換える

Blazor WebAssembly アプリ内のページ コンポーネントに対するルーティング要求は、Blazor Server アプリでのルーティング要求のように単純なものではありません。 次の 2 つのコンポーネントがある Blazor WebAssembly アプリについて考えてみます。

  • Main.razor:アプリのルートで読み込まれ、About コンポーネントへのリンク (href="About") が含まれています。
  • About.razor: About コンポーネント。

アプリの既定のドキュメントがブラウザーのアドレス バー (例: https://www.contoso.com/) を使用して要求された場合:

  1. ブラウザーにより要求が送信されます。
  2. 既定のページ (通常は index.html) が返されます。
  3. index.html によりアプリがブートストラップされます。
  4. Router コンポーネントが読み込まれて、RazorMain コンポーネントがレンダリングされます。

Main ページでは、About コンポーネントへのリンクの選択がクライアント上で動作します。Blazor のルーターにより、インターネット上で www.contoso.comAbout を求めるブラウザーの要求が停止され、レンダリングされた About コンポーネント自体が提供されるためです。 " Blazor WebAssembly アプリ内にある" 内部エンドポイントへの要求は、すべて同じように動作します。要求によって、サーバーにホストされているインターネット上のリソースに対するブラウザーベースの要求がトリガーされることはありません。 要求は、ルーターによって内部的に処理されます。

ブラウザーのアドレス バーを使用して www.contoso.com/About の要求が行われた場合、その要求は失敗します。 アプリのインターネット ホスト上にそのようなリソースは存在しないため、"404 見つかりません" という応答が返されます。

ブラウザーではクライアント側ページの要求がインターネットベースのホストに対して行われるため、Web サーバーとホスティング サービスでは、サーバー上に物理的に存在しないリソースに対する index.html ページへのすべての要求を、書き換える必要があります。 index.html が返されると、アプリの Blazor ルーターがそれを受け取り、正しいリソースで応答します。

IIS サーバーに展開する場合は、アプリで発行される web.config ファイルで URL Rewrite Module を使用できます。 詳細については、「IIS」セクションを参照してください。

ASP.NET Core でのホストされた展開

"ホストされたデプロイ" により、Blazor WebAssembly アプリが、Web サーバー上で実行されている ASP.NET Core アプリからブラウザーに提供されます。

クライアント Blazor WebAssembly アプリは、サーバー アプリの他の静的な Web アセットと共に、サーバー アプリの /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot フォルダーに発行されます。 2 つのアプリが一緒に展開されます。 ASP.NET Core アプリをホストできる Web サーバーが必要です。 ホストされている展開の場合、Visual Studio には Blazor WebAssembly アプリ プロジェクト テンプレートが含まれており (dotnet new コマンドを使用する場合は blazorwasm テンプレート)、 Hosted オプションが選択されています (dotnet new コマンドを使用する場合は -ho|--hosted)。

詳細については、次の記事を参照してください。

特定のプラットフォーム用のフレームワークに依存する実行可能ファイルのホストされた展開

ホストされた Blazor WebAssembly アプリを (自己完結型ではなく) 特定のプラットフォームのフレームワーク依存実行可能ファイルとして展開するには、使用中のツールに基づいて次のガイダンスを使用します。

Visual Studio

既定では、生成された発行プロファイル (.pubxml) に対して自己完結型展開が構成されます。 Server プロジェクトの発行プロファイルに false に設定された <SelfContained> MSBuild プロパティが含まれていることを確認します。

Server プロジェクトの Properties フォルダー内の .pubxml 発行プロファイル ファイルで、次の手順を実行します。

<SelfContained>false</SelfContained>

発行 UI の [設定] 領域にある [ターゲット ランタイム] 設定を使用してランタイム識別子 (RID) を設定します。これにより、発行プロファイルに <RuntimeIdentifier> MSBuild プロパティが生成されます。

<RuntimeIdentifier>{RID}</RuntimeIdentifier>

上記の構成では、{RID} プレースホルダーはランタイム識別子 (RID) です。

Serverリリース構成で プロジェクトを発行します。

注意

/p:PublishProfile={PROFILE}dotnet publish コマンドに渡すことで、.NET CLI を使用して発行プロファイル設定でアプリを発行できます。ここで {PROFILE} プレースホルダーはプロファイルです。 詳細については、「ASP.NET Core アプリを配置するための Visual Studio 発行プロファイル (.pubxml)」の記事の「プロファイルを発行する」と「フォルダー発行の例」のセクションを参照してください。 発行プロファイルではなく dotnet publish コマンドで RID を渡す場合は、-r|--runtime オプション "ではなく"、コマンドで MSBuild プロパティ (/p:RuntimeIdentifier) を使用します。

.NET CLI

Server プロジェクトのプロジェクト ファイル内の <PropertyGroup><SelfContained> MSBuild プロパティを false に設定して、自己完結型の展開を構成します。

<SelfContained>false</SelfContained>

重要

SelfContained プロパティは、Server プロジェクトのプロジェクト ファイルに配置する必要があります。 このプロパティは、--no-self-contained オプションまたは MSBuild プロパティ /p:SelfContained=false を使用する dotnet publish コマンドを使用して正しく設定できません。

次の "いずれか" の方法を使用してランタイム識別子 (RID) を設定します。

  • オプション 1: Server プロジェクトのプロジェクト ファイルにある <PropertyGroup> に RID を設定します。

    <RuntimeIdentifier>{RID}</RuntimeIdentifier>
    

    上記の構成では、{RID} プレースホルダーはランタイム識別子 (RID) です。

    Server プロジェクトからリリース構成でアプリを発行します。

    dotnet publish -c Release
    
  • オプション 2: dotnet publish コマンドで RID を MSBuild プロパティ (/p:RuntimeIdentifier) として渡します。-r|--runtime オプションは "使いません"。

    dotnet publish -c Release /p:RuntimeIdentifier={RID}
    

    上記のコマンドでは、{RID} プレースホルダーはランタイム識別子 (RID) です。

詳細については、次の記事を参照してください。

複数の Blazor WebAssembly アプリによるホストされた展開

詳細については、「複数のホストされた ASP.NET Core Blazor WebAssembly アプリ」を参照してください。

スタンドアロン展開

"スタンドアロン デプロイ" により、Blazor WebAssembly アプリが、クライアントによって直接要求される静的ファイルのセットとして提供されます。 任意の静的ファイル サーバーで Blazor アプリを提供できます。

スタンドアロンのデプロイ アセットは、/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot フォルダーに発行されます。

Azure App Service

Blazor WebAssembly アプリは、IIS 上でアプリをホストするために使用される Windows 上の Azure App Service にデプロイできます。

スタンドアロンの Blazor WebAssembly アプリを Azure App Service for Linux にデプロイすることは、現在サポートされていません。 スタンドアロンの Blazor WebAssembly アプリは、このシナリオをサポートしている Azure Static Web Apps を使ってホストすることをお勧めします。

Azure Static Web Apps

次のいずれかの方法を使用して、Blazor WebAssembly アプリを Azure Static Web Apps にデプロイします。

Visual Studio からデプロイする

Visual Studio からデプロイするには、Azure Static Web Apps の発行プロファイルを作成します。

  1. プロセス中に Visual Studio の再起動が必要になる場合があるため、保存されていない作業をプロジェクトに保存します。

  2. Visual Studio の [発行] UI で、[ターゲット]>[Azure]>[特定のターゲット]>[Azure Static Web Apps] を選択して、発行プロファイルを作成します。

  3. Visual Studio 用 Azure WebJobs ツール コンポーネントがインストールされていない場合は、ASP.NET および Web 開発コンポーネントをインストールするように求めるプロンプトが表示されます。 プロンプトに従って、Visual Studio インストーラーを使用してツールをインストールします。 Visual Studio は、ツールのインストール中に自動的に閉じて再び開きます。 ツールがインストールされたら、最初のステップからやり直して発行プロファイルを作成します。

  4. 発行プロファイルの構成で、サブスクリプション名を指定します。 既存のインスタンスを選択するか、[新しいインスタンスの作成] を選択します。 Azure portal の [静的 Web アプリの作成] UI で新しいインスタンスを作成する場合は、[デプロイの詳細]>[ソース][その他] に設定します。 Azure portal でデプロイが完了するまで待ってから、先に進んでください。

  5. 発行プロファイルの構成で、インスタンスのリソース グループから Azure Static Web Apps インスタンスを選択します。 [完了] を選択して、発行プロファイルを作成します。 Visual Studio で Static Web Apps (SWA) CLI のインストールを求められた場合は、プロンプトに従って CLI をインストールします。 SWA CLI には NPM または Node.js (Visual Studio のドキュメント) が必要です。

発行プロファイルが作成されたら、[発行] ボタンを選択し、発行プロファイルを使用してアプリを Azure Static Web Apps インスタンスにデプロイします。

GitHub からのデプロイ

GitHub リポジトリからデプロイするには、Azure Static Web Apps で Blazor を使用して静的 Web アプリをビルドするためのチュートリアルを参照してください。

IIS

IIS は、Blazor アプリ対応の静的ファイル サーバーです。 Blazor をホストするよう IIS を構成する方法については、「IIS で静的 Web サイトを構築する」を参照してください。

発行されたアセットは、使用されている SDK のバージョンと、{TARGET FRAMEWORK} プレースホルダーがターゲット フレームワークになっている場所に応じて、/bin/Release/{TARGET FRAMEWORK}/publish または bin\Release\{TARGET FRAMEWORK}\browser-wasm\publish フォルダーに作成されます。 publish フォルダーのコンテンツを、Web サーバーまたはホスティング サービス上でホストします。

web.config

Blazor プロジェクトが発行されると、web.config ファイルが以下の IIS 構成で作成されます。

  • MIME タイプ
  • 次の MIME の種類に対しては、HTTP 圧縮が有効にされます。
    • application/octet-stream
    • application/wasm
  • URL Rewrite Module のルールが確立されます。
    • アプリの静的なアセットが存在するサブディレクトリ (wwwroot/{PATH REQUESTED}) が提供されます。
    • ファイル以外のアセットの要求が、アプリの静的アセット フォルダー内の既定のドキュメント (wwwroot/index.html) にリダイレクトされるように、SPA フォールバック ルーティングが作成されます。

カスタム web.config を使用する

カスタム web.config ファイルを使用するには、次のようにします。

  1. カスタム web.config ファイルをプロジェクトのルート フォルダーに配置します。
  2. プロジェクトを発行します。 詳しくは、「ASP.NET Core Blazor のホストと展開」をご覧ください。
  1. カスタム web.config ファイルをプロジェクトのルート フォルダーに配置します。 ホストされている Blazor WebAssemblyソリューションの場合は、ファイルを Server プロジェクトのフォルダーに配置します。
  2. プロジェクトを発行します。 ホストされている Blazor WebAssembly ソリューションの場合は、Server プロジェクトからソリューションを発行します。 詳細については、「ASP.NET Core Blazor のホストと展開」を参照してください。

発行中の SDK の web.config の生成または変換が、publish フォルダー内の発行済みアセットにファイルを移動しない場合、またはカスタム web.config ファイル内のカスタム構成を変更する場合は、必要に応じて次のいずれかの方法を使用してプロセスを完全に制御します。

  • たとえば、SDK がファイルを生成しない場合は、使用されている SDK のバージョンと {TARGET FRAMEWORK} プレースホルダーがターゲット フレームワークになっている場所に応じて、/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot または bin\Release\{TARGET FRAMEWORK}\browser-wasm\publish のスタンドアロン Blazor WebAssembly アプリで、プロジェクト ファイル (.csproj) で <PublishIISAssets> プロパティを true に設定します。 スタンドアロン WebAssembly アプリの場合は通常、カスタム web.config ファイルを移動し、SDK によるファイルの変換を防止するために必要な設定はこれだけです。

    <PropertyGroup>
      <PublishIISAssets>true</PublishIISAssets>
    </PropertyGroup>
    
  • プロジェクト ファイル (.csproj) で SDK の web.config の変換を無効にします。

    <PropertyGroup>
      <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    </PropertyGroup>
    
  • プロジェクト ファイル (.csproj) にカスタム ターゲットを追加して、カスタム web.config ファイルを移動します。 次の例では、カスタム web.config ファイルは開発者によってプロジェクトのルートに配置されます。 web.config ファイルが他の場所にある場合は、SourceFiles でファイルへのパスを指定します。 次の例では、$(PublishDir)publish フォルダーを指定していますが、カスタム出力場所に DestinationFolder へのパスを指定しています。

    <Target Name="CopyWebConfig" AfterTargets="Publish">
      <Copy SourceFiles="web.config" DestinationFolder="$(PublishDir)" />
    </Target>
    

URL リライト モジュールをインストールする

URL Rewrite Module は、URL の書き換えに必要となります。 このモジュールは既定ではインストールされていません。また、Web サーバー (IIS) の役割サービス機能としてインストールすることはできません。 モジュールは、IIS Web サイトからダウンロードする必要があります。 Web Platform Installer を使用してモジュールをインストールします。

  1. ローカルで、URL Rewrite Module のダウンロード ページに移動します。 英語版については、WebPI を選択して WebPI インストーラーをダウンロードします。 その他の言語版については、サーバーの適切なアーキテクチャ (x86/x64) を選択して、インストーラーをダウンロードします。
  2. インストーラーをサーバーにコピーします。 インストーラーを実行します。 [インストール] ボタンを選択して、ライセンス条項に同意します。 インストールが完了した後、サーバーの再起動は必要はありません。

Web サイトを構成する

Web サイトの物理パスをアプリのフォルダーに設定します。 フォルダーには次のものが含まれます。

  • web.config ファイル。IIS ではこのファイルを使用して、必要なリダイレクト ルールやファイルのコンテンツの種類など、Web サイトの構成が行われます。
  • アプリの静的なアセット フォルダー。

IIS サブアプリとしてホストする

スタンドアロン アプリが IIS サブアプリとしてホストされている場合は、次のいずれかを実行します。

  • 継承された ASP.NET Core モジュール ハンドラーを無効にします。

    Blazor アプリで発行された web.config ファイル内のハンドラーを、<handlers> セクションをファイルの <system.webServer> セクションに追加することで削除します。

    <handlers>
      <remove name="aspNetCore" />
    </handlers>
    
  • inheritInChildApplicationsfalse に設定された <location> 要素を使用して、ルート (親) アプリの <system.webServer> セクションの継承を無効にします。

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <location path="." inheritInChildApplications="false">
        <system.webServer>
          <handlers>
            <add name="aspNetCore" ... />
          </handlers>
          <aspNetCore ... />
        </system.webServer>
      </location>
    </configuration>
    

    Note

    ルート (親) アプリの <system.webServer> セクションの継承を無効にするのは、.NET SDK を使用した発行済みアプリの既定の構成です。

ハンドラーの削除または継承の無効化は、アプリの基本パスの構成に加えて行われます。 IIS でサブアプリを構成するときに、アプリの index.html ファイル内のアプリのベース パスを、使用している IIS の別名に設定します。

ASP.NET Core Blazor のホストと展開」の記事に記載されているガイダンスに従って、アプリのベース パスを構成します。

Brotli と Gzip の圧縮

このセクションは、スタンドアロンの Blazor WebAssembly アプリにのみ適用されます。

このセクションは、スタンドアロンの Blazor WebAssembly アプリにのみ適用されます。 ホストされている Blazor アプリでは、このセクションにリンクされているファイルではなく、既定の ASP.NET Core アプリ web.config ファイルが使用されます。

web.config を使用して、スタンドアロンの Blazor WebAssembly 用に Brotli または Gzip で圧縮された Blazor アセットを提供するように IIS を構成できます。 構成ファイルの例については、web.config をご覧ください。

次のシナリオでは、サンプル web.config ファイルを追加で構成することが必要になる場合があります。

  • このアプリの仕様では、次のいずれかが呼び出されます。
    • サンプル web.config ファイルで構成されていない使用中の圧縮ファイル。
    • サンプル web.config ファイルで非圧縮形式で構成されている使用中の圧縮ファイル。
  • サーバーの IIS 構成 (applicationHost.config など) では、サーバーレベルの IIS の既定値が提供されています。 サーバーレベルの構成によっては、サンプル web.config ファイルに含まれるものとは異なる IIS 構成が必要になる場合があります。

カスタム web.config ファイルの詳細については、「カスタム web.config を使用する」セクションを参照してください。

トラブルシューティング

Web サイトの構成にアクセスしようとしたときに、"500 - 内部サーバー エラー" という応答が返され、IIS マネージャーによりエラーがスローされた場合は、URL リライト モジュールがインストールされていることを確認します。 モジュールがインストールされていない場合、IIS では web.config ファイルを解析できません。 これは、IIS マネージャーによる Web サイトの構成の読み込み、そして Web サイトによる Blazor の静的ファイルの提供を阻止するためのものです。

IIS への展開のトラブルシューティングについて詳しくは、「Azure App Service および IIS での ASP.NET Core のトラブルシューティング」を参照してください。

Azure Storage

Azure Storage の静的ファイル ホスティングにより、サーバーレス Blazor アプリ ホスティングが可能になります。 カスタム ドメイン名の Azure Content Delivery Network (CDN) と HTTPS がサポートされています。

ストレージ アカウントでホスティングされている静的 Web サイトに Blob service サービスが有効になっているとき:

  • インデックス ドキュメント名index.html に設定します。
  • エラー ドキュメント パスindex.html に設定します。 Razor コンポーネントとその他の非ファイル エンドポイントは、Blob service で保管される静的コンテンツの物理パスに置かれません。 このようなリソースの 1 つに対して受け取った要求を Blazor ルーターで処理しなければならないとき、Blob service によって生成された 404 - Not Found エラーにより、要求がエラー ドキュメント パスに転送されます。 index.html BLOB が返され、Blazor ルーターでパスが読み込まれ、処理されます。

ファイルの Content-Type ヘッダーに不適切な MIME の種類があるために、実行時にファイルが読み込まれない場合は、次のいずれかの操作を実行します。

  • ファイルの展開時に適切な MIME の種類 (Content-Type ヘッダー) を設定するようにツールを構成します。

  • アプリの展開後に、ファイルの MIME の種類 (Content-Type ヘッダー) を変更します。

    Storage Explorer (Azure portal) で、ファイルごとに次のようにします。

    1. ファイルを右クリックし、 [プロパティ] を選択します。
    2. ContentType を設定し、 [保存] ボタンを選択します。

詳細については、「Azure Storage での静的 Web サイト ホスティング」を参照してください。

Nginx

以下に示す nginx.conf ファイルは、Nginx が対応するファイルをディスク上で見つけられないときに index.html ファイルを送信するよう Nginx を構成する方法を示すために、簡略化されています。

events { }
http {
    server {
        listen 80;

        location / {
            root      /usr/share/nginx/html;
            try_files $uri $uri/ /index.html =404;
        }
    }
}

NGINX バースト レート制限limit_req で設定するとき、アプリによって行われる比較的大量の要求を受け入れる目的で、場合によっては、Blazor WebAssembly アプリの burst パラメーター値を大きくする必要があります。 最初に、値を 60 以上に設定します。

http {
    server {
        ...

        location / {
            ...

            limit_req zone=one burst=60 nodelay;
        }
    }
}

"503 - サービスを利用できません" という状態コードを要求が受信していることがブラウザー開発者ツールまたはネットワーク トラフィック ツールで示されている場合、この値を増やします。

運用環境での Nginx Web サーバーの構成に関する詳細については、「Creating NGINX Plus and NGINX Configuration Files」 (NGINX Plus と NGINX 構成ファイルの作成) を参照してください。

Apache

Blazor WebAssembly アプリを CentOS 7 以降にデプロイするには:

  1. Apache 構成ファイルを作成します。 次の例は、簡略化された構成ファイル (blazorapp.config) です。
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias *.example.com

    DocumentRoot "/var/www/blazorapp"
    ErrorDocument 404 /index.html

    AddType application/wasm .wasm

    <Directory "/var/www/blazorapp">
        Options -Indexes
        AllowOverride None
    </Directory>

    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
    </IfModule>

    ErrorLog /var/log/httpd/blazorapp-error.log
    CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias *.example.com

    DocumentRoot "/var/www/blazorapp"
    ErrorDocument 404 /index.html

    AddType application/wasm .wasm
    AddType application/octet-stream .dll

    <Directory "/var/www/blazorapp">
        Options -Indexes
        AllowOverride None
    </Directory>

    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
    </IfModule>

    ErrorLog /var/log/httpd/blazorapp-error.log
    CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>
  1. Apache 構成ファイルを /etc/httpd/conf.d/ ディレクトリ (CentOS 7 の既定の Apache 構成ディレクトリ) に配置します。

  2. アプリのファイルを /var/www/blazorapp ディレクトリ (構成ファイルで DocumentRoot に指定された場所) に配置します。

  3. Apache サービスを再起動します。

詳細については、次のトピックを参照してください。 mod_mime および mod_deflate

GitHub ページ

ページをデプロイする既定の GitHub アクションでは、アンダースコアで始まるフォルダー (_framework フォルダーなど) のデプロイがスキップされます。 アンダースコアで始まるフォルダーをデプロイするには、空の .nojekyll ファイルを Git ブランチに追加します。

Git では、blazor.webassembly.js などの JavaScript (JS) ファイルをテキストとして扱い、行の終わりを CRLF (キャリッジ リターン/ライン フィード) からデプロイ パイプラインの LF (ライン フィード) に変換します。 JS ファイルに対するこれらの変更により、blazor.boot.json ファイル内のクライアントに Blazor で送信するものとは異なるファイル ハッシュが生成されます。 この不一致により、クライアントで整合性チェック エラーが発生します。 この問題を解決する方法の 1 つは、アプリのアセットを Git ブランチに追加する前に、*.js binary 行を含む .gitattributes ファイルを追加することです。 *.js binary 行では、JS ファイルをバイナリ ファイルとして扱うように Git が構成されるため、デプロイ パイプラインでのファイルの処理が回避されます。 未処理ファイルのファイル ハッシュは、blazor.boot.json ファイル内のエントリと一致し、クライアント側の整合性チェックに合格します。 詳細については、「ASP.NET Core Blazor WebAssembly .NET ランタイムとアプリ バンドル キャッシュ」を参照してください。

URL の書き換えを処理するために、wwwroot/404.html ファイルを、要求を index.html ページにリダイレクトするスクリプトと共に追加します。 例については、SteveSandersonMS/BlazorOnGitHubPages GitHub リポジトリを参照してください。

組織のサイトではなくプロジェクトのサイトを使用しているときは、wwwroot/index.html 内の <base> タグを更新します。 href 属性の値を、GitHub リポジトリの名前の末尾にスラッシュを付けたもの (例: /my-repository/) に設定します。 SteveSandersonMS/BlazorOnGitHubPages GitHub リポジトリでは、.github/workflows/main.yml 構成ファイルによる発行時に、ベースの href が更新されます。

Note

SteveSandersonMS/BlazorOnGitHubPages GitHub リポジトリは、.NET Foundation または Microsoft では所有、管理、またはサポートされていません。

Docker によるスタンドアロン

スタンドアロン Blazor WebAssembly アプリは、静的ファイル サーバーによってホストされる静的ファイルのセットとして公開されます。

Docker でアプリをホストするには、次のようにします。

  • Ngnix や Apache など、Web サーバーがサポートされている Docker コンテナーを選択します。
  • 静的ファイルを提供するために、Web サーバーで定義されている場所フォルダーに publish フォルダー資産をコピーします。
  • 必要に応じて追加の構成を適用して、Blazor WebAssembly アプリを提供します。

構成のガイダンスについては、次のリソースを参照してください。

ホストの構成値

Blazor WebAssembly アプリでは、開発環境での実行時に以下のホスト構成値をコマンドライン引数として受け入れることができます。

コンテンツ ルート

--contentroot 引数では、アプリのコンテンツ ファイルを含むディレクトリへの絶対パスが設定されます (コンテンツ ルート)。 次の例では、/content-root-path はアプリのコンテンツ ルート パスです。

  • コマンド プロンプトでアプリをローカルに実行するときに、引数を渡します。 アプリのディレクトリから、次のコマンドを実行します。

    dotnet run --contentroot=/content-root-path
    
  • IIS Express プロファイル内のアプリの launchSettings.json ファイルに、エントリを追加します。 この設定は、Visual Studio デバッガーを使用し、コマンド プロンプトから dotnet run でアプリが実行されるときに使用されます。

    "commandLineArgs": "--contentroot=/content-root-path"
    
  • Visual Studio の [プロパティ]>[デバッグ]>[アプリケーションの引数] で、引数を指定します。 Visual Studio のプロパティ ページで引数を設定すると、その引数が launchSettings.json ファイルに追加されます。

    --contentroot=/content-root-path
    

パス ベース

--pathbase 引数により、ルート以外の相対 URL パスでローカルで実行されているアプリに対して、アプリのベース パスを設定することができます (ステージングと運用環境の場合、<base> タグ href/ 以外のパスに設定されます)。 次の例では、/relative-URL-path はアプリのパス ベースです。 詳細については、「アプリのベースパス」を参照してください。

重要

<base> タグの href に指定するパスとは異なり、--pathbase 引数値を渡すときはスラッシュ (/) を末尾に含めないでください。 <base> タグでアプリのベース パスが <base href="/CoolApp/"> と指定されている場合 (末尾にスラッシュあり)、コマンドライン引数値としては --pathbase=/CoolApp を渡してください (末尾にスラッシュなし)。

  • コマンド プロンプトでアプリをローカルに実行するときに、引数を渡します。 アプリのディレクトリから、次のコマンドを実行します。

    dotnet run --pathbase=/relative-URL-path
    
  • IIS Express プロファイル内のアプリの launchSettings.json ファイルに、エントリを追加します。 この設定は、Visual Studio デバッガーを使用し、コマンド プロンプトから dotnet run でアプリを実行するときに使用されます。

    "commandLineArgs": "--pathbase=/relative-URL-path"
    
  • Visual Studio の [プロパティ]>[デバッグ]>[アプリケーションの引数] で、引数を指定します。 Visual Studio のプロパティ ページで引数を設定すると、その引数が launchSettings.json ファイルに追加されます。

    --pathbase=/relative-URL-path
    

URL

--urls 引数では、要求をリッスンするポートとプロトコルを使用して、IP アドレスまたはホスト アドレスが設定されます。

  • コマンド プロンプトでアプリをローカルに実行するときに、引数を渡します。 アプリのディレクトリから、次のコマンドを実行します。

    dotnet run --urls=http://127.0.0.1:0
    
  • IIS Express プロファイル内のアプリの launchSettings.json ファイルに、エントリを追加します。 この設定は、Visual Studio デバッガーを使用し、コマンド プロンプトから dotnet run でアプリを実行するときに使用されます。

    "commandLineArgs": "--urls=http://127.0.0.1:0"
    
  • Visual Studio の [プロパティ]>[デバッグ]>[アプリケーションの引数] で、引数を指定します。 Visual Studio のプロパティ ページで引数を設定すると、その引数が launchSettings.json ファイルに追加されます。

    --urls=http://127.0.0.1:0
    

Linux でのホストされた展開 (Nginx)

プロキシ サーバーとロード バランサーを使用するために ASP.NET Core を構成する」のガイダンスに従って、ForwardedHeadersOptions を使用して X-Forwarded-ForX-Forwarded-Proto ヘッダーを転送するようにアプリを構成します。

サブアプリのパス構成を含む、アプリの基本パスを設定する方法について詳しくは、「ASP.NET Core Blazor のホストと展開」をご覧ください。

ASP.NET Core SignalR アプリ」のガイダンスに従って、次のように変更します。

  • プロキシ バッファーリング (proxy_buffering off;) の構成は削除します。この設定は、Blazor アプリのクライアントとサーバー間の通信に関連しないサーバー送信イベント (SSE) にのみ適用されるためです。

  • location パスを /hubroute (location /hubroute { ... }) からサブアプリパス /{PATH} (location /{PATH} { ... }) に変更します。ここで、{PATH} プレースホルダーはサブアプリ パスです。

    次の例では、ルート パス / で要求に応答するアプリのサーバーを構成します。

    http {
        server {
            ...
            location / {
                ...
            }
        }
    }
    

    次の例では、/blazor のサブアプリ パスを次のように構成します。

    http {
        server {
            ...
            location /blazor {
                ...
            }
        }
    }
    

詳細および構成のガイダンスについては、次のリソースを参照してください。

トリマーを構成する

Blazor では、出力アセンブリから不要な中間言語 (IL) を削除するために、IL トリミング設定が各リリース ビルド上で実行されます。 詳しくは、「ASP.NET Core Blazor 用のトリマーを構成する」をご覧ください。

リンカーを構成する

Blazor では、出力アセンブリから不要な中間言語 (IL) を削除するために、IL リンク設定が各リリース ビルド上で実行されます。 詳しくは、「ASP.NET Core Blazor 用のリンカーを構成する」をご覧ください。

DLL ファイルのファイル名拡張子を変更する

このセクションは、ASP.NET Core 6.x および 7.x に適用されます。 .NET 8.0 以降の ASP.NET Core では、.NET アセンブリは Webcil ファイル形式を使って WebAssembly ファイル (.wasm) として配置されます。 .NET 8.0 以降の ASP.NET Core では、このセクションは Webcil ファイル形式がアプリのプロジェクト ファイルで無効になっている場合にのみ適用されます。

ファイアウォール、ウイルス対策プログラム、またはネットワーク セキュリティ アプライアンスによってアプリのダイナミック リンク ライブラリ (DLL) ファイル (.dll) の伝送がブロックされる場合は、このセクションのガイダンスのようにして、アプリで発行される DLL ファイルのファイル名拡張子を変更できます。

注意

多くのセキュリティ システムはファイル拡張子をチェックするだけでなく、アプリのファイルの内容をスキャンするため、アプリの DLL ファイルのファイル名拡張子を変更しても、問題が解決しない可能性があります。

DLL ファイルのダウンロードと実行をブロックする環境でより堅牢なアプローチを実現する場合は、.NET 8.0 以降の ASP.NET Core を使います。その場合、既定では、.NET アセンブリは Webcil ファイル形式を使って WebAssembly ファイル (.wasm) としてパッケージ化されます。 詳しくは、この記事のバージョン 8.0 以降の「.NET アセンブリの Webcil パッケージ形式」セクションを参照してください。

この問題に対処するためのサード パーティのアプローチが存在します。 詳しくは、「優れた Blazor」のリソースをご覧ください。

Note

多くのセキュリティ システムはファイル拡張子をチェックするだけでなく、アプリのファイルの内容をスキャンするため、アプリの DLL ファイルのファイル名拡張子を変更しても、問題が解決しない可能性があります。

DLL ファイルのダウンロードと実行をブロックする環境でのより堅牢なアプローチについては、次の "いずれか" のアプローチを採用してください。

  • .NET 8.0 以降の ASP.NET Core を使います。その場合、既定で、.NET アセンブリは Webcil ファイル形式を使って WebAssembly ファイル (.wasm) としてパッケージ化されます。 詳しくは、この記事のバージョン 8.0 以降の「.NET アセンブリの Webcil パッケージ形式」セクションを参照してください。
  • .NET 6.0 以降の ASP.NET Core では、カスタム配置レイアウトを使います。

この問題に対処するためのサード パーティのアプローチが存在します。 詳しくは、「優れた Blazor」のリソースをご覧ください。

アプリを発行した後、シェル スクリプトまたは DevOps ビルド パイプラインを使用して、アプリの発行された出力のディレクトリ内で別のファイル拡張子を使用するように .dll ファイルの名前を変更します。

次の例で以下を実行します。

  • PowerShell (PS) は、ファイル拡張子を更新するために使用されます。
  • .dll ファイルの名前は、コマンド ラインからファイル拡張子 .bin を使用するように変更されます。
  • ファイル拡張子 .dll を持つ、発行された blazor.boot.json ファイルに一覧表示されているファイルは、ファイル拡張子 .bin に更新されます。
  • サービス ワーカー資産も使用されている場合、PowerShell コマンドは service-worker-assets.js ファイルに一覧表示されている .dll ファイルをファイル拡張子 .bin に更新します。

.bin とは異なるファイル拡張子を使用するには、次のコマンド内の .bin を目的のファイル拡張子に置き換えます。

Windows の場合:

dir {PATH} | rename-item -NewName { $_.name -replace ".dll\b",".bin" }
((Get-Content {PATH}\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\blazor.boot.json

上記のコマンドでは、{PATH} プレースホルダーは発行された _framework フォルダーへのパスです (たとえば、プロジェクトのルート フォルダーからの .\bin\Release\net6.0\browser-wasm\publish\wwwroot\_framework)。

サービス ワーカー アセットも使用されている場合:

((Get-Content {PATH}\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\service-worker-assets.js

上記のコマンドでは、{PATH} プレースホルダーは発行された service-worker-assets.js ファイルへのパスです。

Linux または macOS の場合:

for f in {PATH}/*; do mv "$f" "`echo $f | sed -e 's/\.dll/.bin/g'`"; done
sed -i 's/\.dll"/.bin"/g' {PATH}/blazor.boot.json

上記のコマンドでは、{PATH} プレースホルダーは発行された _framework フォルダーへのパスです (たとえば、プロジェクトのルート フォルダーからの .\bin\Release\net6.0\browser-wasm\publish\wwwroot\_framework)。

サービス ワーカー アセットも使用されている場合:

sed -i 's/\.dll"/.bin"/g' {PATH}/service-worker-assets.js

上記のコマンドでは、{PATH} プレースホルダーは発行された service-worker-assets.js ファイルへのパスです。

圧縮された blazor.boot.json.gzblazor.boot.json.br のファイルに対処するには、次のいずれかの方法を採用します。

  • 圧縮された blazor.boot.json.gzblazor.boot.json.br のファイルを削除します。 このアプローチでは、圧縮は無効になっています。
  • 更新した blazor.boot.json ファイルを圧縮します。

圧縮された blazor.boot.json ファイルに関する上記のガイダンスは、サービス ワーカー アセットが使用されている場合にも適用されます。 service-worker-assets.js.brservice-worker-assets.js.gz を削除または再圧縮します。 そうしないと、ブラウザーでのファイルの整合性チェックが失敗します。

.NET 6 に関する次の Windows の例では、プロジェクトのルートに配置された PowerShell スクリプトを使用しています。 圧縮を無効にする次のスクリプトは、blazor.boot.json ファイルを再圧縮する場合の追加の変更の基礎となります。

ChangeDLLExtensions.ps1::

param([string]$filepath,[string]$tfm)
dir $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework | rename-item -NewName { $_.name -replace ".dll\b",".bin" }
((Get-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json.gz
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json.br

サービス ワーカー アセットも使用されている場合は、次のコマンドを追加します。

((Get-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js.gz
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js.br

プロジェクト ファイルでは、Release 構成のアプリの発行後にスクリプトが実行されます。

<Target Name="ChangeDLLFileExtensions" AfterTargets="AfterPublish" Condition="'$(Configuration)'=='Release'">
  <Exec Command="powershell.exe -command &quot;&amp; { .\ChangeDLLExtensions.ps1 '$(SolutionDir)' '$(TargetFramework)'}&quot;" />
</Target>

Note

同じアセンブリの名前変更と遅延読み込みについては、「ASP.NET Core Blazor WebAssembly でのアセンブリの遅延読み込み」のガイダンスをご覧ください。

通常、アプリのサーバーでは、更新された拡張子を持つファイルを提供するために静的資産構成が必要です。 IIS でホストされているアプリの場合は、カスタム web.config ファイルの静的コンテンツ セクション (<staticContent>) に、新しいファイル拡張子の MIME マップ エントリ (<mimeMap>) を追加します。 次の例では、ファイル拡張子が .dll から .bin に変更されていることを前提としています。

<staticContent>
  ...
  <mimeMap fileExtension=".bin" mimeType="application/octet-stream" />
  ...
</staticContent>

圧縮が使用されている場合は、圧縮済みファイルの更新プログラムを含めます。

<mimeMap fileExtension=".bin.br" mimeType="application/octet-stream" />
<mimeMap fileExtension=".bin.gz" mimeType="application/octet-stream" />

.dll ファイル拡張子のエントリを削除します。

- <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />

圧縮が使用されている場合は、圧縮済み .dll ファイルのエントリを削除します。

- <mimeMap fileExtension=".dll.br" mimeType="application/octet-stream" />
- <mimeMap fileExtension=".dll.gz" mimeType="application/octet-stream" />

カスタム web.config ファイルの詳細については、「カスタム web.config を使用する」セクションを参照してください。

以前の展開の破損

通常は展開時に、次のようになります。

  • 変更されたファイルのみが置き換えられます。通常は、展開が高速になります。
  • 新しい展開の一部ではない既存のファイルは、新しい展開で使用するために残されています。

まれなケースとして、以前の展開の残留ファイルによって新しい展開が破損することがあります。 既存の展開 (または、展開前にローカルで発行されたアプリ) を完全に削除すると、展開が破損している問題が解決される場合があります。 多くの場合、既存の展開を一度削除するだけで問題を解決できます。これには、DevOps のビルドと配置のパイプラインが含まれます。

DevOps のビルドと配置のパイプラインが使用されているときに、以前の展開をクリアする必要があると判断した場合は、ビルド パイプラインにステップを一時的に追加して、破損の正確な原因をトラブルシューティングするまで、新しく展開するごとに前の展開を削除することができます。

整合性チェックの失敗を解決する

Blazor WebAssembly によってアプリのスタートアップ ファイルがダウンロードされると、応答に対して整合性チェックを実行するようにブラウザーに指示が出されます。 Blazor は、DLL (.dll)、WebAssembly (.wasm)、および blazor.boot.json ファイル内の他のファイルの SHA-256 ハッシュ値を送信します。これはクライアントにキャッシュされません。 キャッシュされたファイルのファイル ハッシュは、blazor.boot.json ファイル内のハッシュと比較されます。 キャッシュされたファイルのハッシュが一致する場合は、キャッシュされたファイルが Blazor で使われます。 それ以外の場合、サーバーのファイルが要求されます。 ファイルがダウンロードされた後、整合性の検証のためにそのハッシュが再度チェックされます。 ダウンロードされたファイルの整合性チェックが失敗した場合、ブラウザーによってエラーが生成されます。

ファイルの整合性を管理するための Blazor のアルゴリズム:

  • たとえば、ユーザーがアプリケーション ファイルをダウンロードしている間に、Web サーバーに新しい展開が適用された場合などに、アプリによって整合性のないファイルのセットが読み込まれるリスクがないことが保証されます。 ファイルに整合性がないと、アプリが誤動作する可能性があります。
  • ユーザーのブラウザーによって不整合のない応答や無効な応答がキャッシュされないことが保証されます。そのようなことがあると、ユーザーがページを手動で更新してもアプリを起動できなくなる可能性があります。
  • 応答をキャッシュし、想定される SHA-256 ハッシュ自体の変更までサーバー側の変更をチェックしなくても安全になるため、後続のページ読み込みに伴う要求の数が減り、速く完了するようになります。

想定される SHA-256 ハッシュに一致しない応答が Web サーバーから返された場合、ブラウザーの開発者コンソールに次の例のようなエラーが表示されます。

Failed to find a valid digest in the 'integrity' attribute for resource 'https://myapp.example.com/_framework/MyBlazorApp.dll' with computed SHA-256 integrity 'IIa70iwvmEg5WiDV17OpQ5eCztNYqL186J56852RpJY='. (計算された SHA-256 整合性 'IIa70iwvmEg5WiDV17OpQ5eCztNYqL186J56852RpJY=' を持つリソース 'https://myapp.example.com/_framework/MyBlazorApp.dll' の 'integrity' 属性に有効なダイジェストが見つかりませんでした。) The resource has been blocked. (リソースがブロックされています。)

ほとんどの場合、この警告は整合性チェックに関する問題を示していません。 代わりに、通常、警告は他の問題が存在することを意味します。

Blazor WebAssembly のブート参照ソースについては、dotnet/aspnetcore GitHub リポジトリの Boot.WebAssembly.ts ファイルをご覧ください。

注意

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

整合性に関する問題の診断

アプリがビルドされるときに生成される blazor.boot.json マニフェストに、ビルド出力が生成された時点でのブート リソースの SHA-256 ハッシュが記述されています。 整合性チェックは、blazor.boot.json の SHA-256 ハッシュがブラウザーに配信されるファイルと一致している限り成功します。

これが失敗する一般的な理由は次のとおりです。

  • Web サーバーからの応答が、ブラウザーが要求したファイルではなく、エラー (たとえば 404 - Not Found500 - Internal Server Error) である場合。 これはブラウザーによって、応答エラーとしてではなく整合性チェックの失敗として報告されます。
  • ファイルのビルドからブラウザーへの配信の間に、何らかによってファイルの内容が変更された場合。 次のような場合に発生します。
    • ユーザーまたはビルド ツールによって、ビルド出力が手動で変更された場合。
    • 展開プロセスの何らかの側面によってファイルが変更された場合。 たとえば、Git ベースの展開メカニズムを使用する場合は、Windows でファイルをコミットして Linux でチェックアウトすると、Git によって Windows スタイルの改行コードが Unix スタイルの改行コードに透過的に変換されることに注意してください。 ファイルの改行コードを変更すると、SHA-256 ハッシュが変更されます。 この問題を回避するには、.gitattributes を使用してビルド成果物を binary ファイルとして扱うことを検討してください。
    • Web サーバーによるファイル提供の一環として、その内容が変更された場合。 たとえば、一部のコンテンツ配信ネットワーク (CDN) では、HTML の縮小が自動的に試行され、それによって変更されます。 場合によっては、このような機能を無効にする必要があります。
  • blazor.boot.json ファイルが正しく読み込まれないか、クライアントに誤ってキャッシュされます。 一般的な原因は次のどちらかです。
    • 正しく構成されていないか、誤動作しているカスタム開発者コード。
    • 1 つ以上の正しく構成されていない中間キャッシュ レイヤー。

これらのうちどれが自分のケースに当てはまるか診断するには:

  1. エラー メッセージを確認し、エラーをトリガーしているファイルをメモします。
  2. ブラウザーの開発者ツールを開き、 [ネットワーク] タブを確認します。必要に応じて、ページを再度読み込み、要求と応答の一覧を表示します。 その一覧でエラーをトリガーしているファイルを見つけます。
  3. 応答に含まれる HTTP 状態コードを確認します。 サーバーから 200 - OK (または別の 2xx 状態コード) 以外のものが返された場合は、サーバー側に診断すべき問題があります。 たとえば、状態コード 403 は承認に関する問題があることを意味しますが、状態コード 500 は、サーバーが未指定のエラーで失敗していることを意味します。 サーバー側のログを参照してアプリを診断し、修正してください。
  4. リソースに対する状態コードが 200 - OK の場合は、ブラウザーの開発者ツールで応答の内容を確認し、その内容が予想されるデータと一致していることを確認します。 たとえば、よくある問題は、他のファイルに対しても要求から index.html データが返されるように、ルーティングを誤って構成してしまうことです。 .wasm 要求への応答が WebAssembly であり、.dll 要求への応答が .NET アセンブリ バイナリであることを確認してください。 そうでない場合、サーバー側のルーティングに関する問題を診断する必要があります。
  5. 整合性 PowerShell スクリプトのトラブルシューティング」で、アプリの発行および展開された出力を検証しようと試みます。

サーバーから正しいと思われるデータが返されていることを確認した場合は、ファイルのビルドと配布の間で何か別の原因によって内容が変更されています。 これを調査するには:

  • ファイルがビルドされた後にファイルが変更される場合に備えて、ビルド ツールチェーンと展開メカニズムを調べます。 この例としては、前に説明したように、Git によってファイルの改行コードが変換される場合が挙げられます。
  • 応答を動的に変更する (たとえば、HTML を縮小しようとする) ように設定されている場合があるため、Web サーバーまたは CDN の構成を確認します。 Web サーバーに HTTP 圧縮が実装されていても問題ありません (たとえば content-encoding: brcontent-encoding: gzip が返される場合)。これは展開後の結果には影響しないためです。 ただし、Web サーバーによって圧縮されていないデータが変更される場合は "問題があります"。

整合性 PowerShell スクリプトのトラブルシューティング

integrity.ps1 PowerShell スクリプトを使用して、発行および展開された Blazor アプリを検証します。 このスクリプトは、アプリに Blazor フレームワークでは特定できない整合性の問題がある場合の出発点として PowerShell Core 7 以降向けに提供されています。 バージョン 7.2.0 より後のバージョンの PowerShell で実行する場合など、スクリプトのカスタマイズが必要になることがあります。

スクリプトを実行すると、publish フォルダー内のファイルと展開されたアプリからダウンロードしたファイルがチェックされ、整合性ハッシュを含むさまざまなマニフェストの問題が検出されます。 これらのチェックにより、最も一般的な問題が検出されます。

  • 発行された出力で、知らずにファイルを変更した。
  • アプリが展開ターゲットに正しく展開されなかった、または展開ターゲットの環境内で何かが変更された。
  • 展開されたアプリと、アプリの発行からの出力の間に違いがある。

PowerShell コマンド シェルで次のコマンドを使用してスクリプトを呼び出します。

.\integrity.ps1 {BASE URL} {PUBLISH OUTPUT FOLDER}

次の例では、https://localhost:5001/ のローカルで実行されているアプリでスクリプトが実行されています。

.\integrity.ps1 https://localhost:5001/ C:\TestApps\BlazorSample\bin\Release\net6.0\publish\

プレースホルダー:

  • {BASE URL}: 展開されたアプリの URL。 末尾のスラッシュ (/) が必要です。
  • {PUBLISH OUTPUT FOLDER}: アプリの publish フォルダー、またはアプリが展開のために発行される場所へのパス。

Note

dotnet/AspNetCore.Docs GitHub リポジトリを複製するときに、integrity.ps1 スクリプトが Bitdefender またはシステムに存在する別のウイルス検索プログラムによって検疫されている可能性があります。 通常、このファイルはウイルス検索プログラムのヒューリスティック スキャン テクノロジによってトラップされます。マルウェアの存在を示す可能性のあるファイルのパターンを検索するだけです。 ウイルス検索プログラムによってファイルが検疫されないようにするには、リポジトリを複製する前に、ウイルス検索プログラムに例外を追加します。 次の例は、Windows システム上のスクリプトへの一般的なパスです。 他のシステムに必要なパスを調整します。 プレースホルダー {USER} はユーザーのパスのセグメントです。

C:\Users\{USER}\Documents\GitHub\AspNetCore.Docs\aspnetcore\blazor\host-and-deploy\webassembly\_samples\integrity.ps1

警告: ウイルス検索プログラムの例外作成は危険であるため、ファイルが安全であることがわかっている場合にのみ実行してください。

ファイルのチェックサムを有効なチェックサム値と比較しても、ファイルの安全性は保証されませんが、悪意のあるユーザーにとってはチェックサム値を維持するようにファイルを変更するのは簡単ではありません。 そのため、チェックサムは一般的なセキュリティ アプローチとして役立ちます。 ローカル integrity.ps1 ファイルのチェックサムを次のいずれかの値と比較します。

  • SHA256: 32c24cb667d79a701135cb72f6bae490d81703323f61b8af2c7e5e5dc0f0c2bb
  • MD5: 9cee7d7ec86ee809a329b5406fbf21a8

次のコマンドを使用して Windows OS でファイルのチェックサムを取得します。 {PATH AND FILE NAME} プレースホルダーのパスとファイル名を指定し、{SHA512|MD5} プレースホルダーに対して生成するチェックサムの種類として、SHA256 または MD5 のいずれかを指定します。

CertUtil -hashfile {PATH AND FILE NAME} {SHA256|MD5}

チェックサムの検証が自身の環境では十分なセキュリティ確保にならないという懸念材料がある場合は、組織のセキュリティのリーダーシップに相談し、ガイダンスを得てください。

詳細については、「Microsoft Defender ウイルス対策による脅威に対する保護の概要」を参照してください。

非 PWA アプリの整合性チェックを無効にする

ほとんどの場合、整合性チェックを無効にしないでください。 整合性チェックを無効にしても、予期しない応答の原因となった根本的な問題は解決されず、前述の利点が失われる結果になります。

Web サーバーから一貫した応答が返されるとは限らないため、基になっている問題が解決されるまで、整合性チェックを一時的に無効にするしかないケースがあります。

整合性チェックを無効にするには、Blazor WebAssembly アプリのプロジェクト ファイル (.csproj) 内のプロパティ グループに次を追加します。

<BlazorCacheBootResources>false</BlazorCacheBootResources>

BlazorCacheBootResources により、SHA-256 ハッシュに基づいて .dll.wasm、およびその他のファイルをキャッシュする Blazor の既定の動作も無効になります。このプロパティによって、SHA-256 ハッシュの正確性を信頼できないことが指定されるためです。 この設定を使用しても、ブラウザーの通常の HTTP キャッシュによってこれらのファイルがキャッシュされる可能性がありますが、このような状況が発生するかどうかは、Web サーバーの構成と、それによって提供される cache-control ヘッダーによって異なります。

Note

BlazorCacheBootResources プロパティによってプログレッシブ Web アプリケーション (PWA) の整合性チェックが無効になることはありません。 PWA に関連するガイダンスについては、「PWA の整合性チェックを無効にする」セクションをご覧ください。

整合性チェックを無効にする必要があるシナリオの完全な一覧を提供することはできません。 サーバーは、Blazor フレームワークの範囲外の任意の方法で要求に応答できます。 フレームワークで提供されている設定 BlazorCacheBootResources を使うと、"アプリで提供できる整合性の保証を失う" のと引き換えに、アプリを実行可能にすることができます。 ここでも、整合性チェックを無効にしないことをお勧めします (特に運用展開の場合)。 開発者は、整合性チェックが失敗する原因になっている、根本的な整合性の問題を解決する必要があります。

整合性の問題が発生する可能性があるいくつかの一般的なケースを次に示します。

  • 整合性をチェックできない HTTP での実行。
  • 展開プロセスによって、発行後のファイルに何らかの変更が加えられる場合。
  • ホストによってファイルに何らかの変更が行われる場合。

PWA の整合性チェックを無効にする

Blazor のプログレッシブ Web アプリケーション (PWA) テンプレートには、オフライン使用のためにアプリケーション ファイルをフェッチおよび格納するための推奨される service-worker.published.js ファイルが含まれています。 これは通常のアプリの起動メカニズムとは別のプロセスであり、独自の整合性チェック ロジックを備えています。

service-worker.published.js ファイル内に、次の行があります。

.map(asset => new Request(asset.url, { integrity: asset.hash }));

整合性チェックを無効にするには、行を次のように変更して integrity パラメーターを削除します。

.map(asset => new Request(asset.url));

ここでも、整合性チェックを無効にすることは、整合性チェックによって提供される安全性の保証が失われることを意味します。 たとえば、ユーザーのブラウザーでアプリをキャッシュしている瞬間に、新しいバージョンを展開した場合、古い展開から一部のファイルがキャッシュされ、新しい展開から別のファイルがキャッシュされるリスクがあります。 そのような場合、さらなる更新プログラムを展開するまで、アプリは破損した状態のままになります。