ASP.NET Core Blazor JavaScript の相互運用性 (JS 相互運用)

Note

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

Blazor アプリでは、.NET メソッドから JavaScript (JS) 関数を呼び出すことも、JS 関数から .NET メソッドを呼び出すこともできます。 これらのシナリオは、"JavaScript 相互運用性" ("JS 相互運用") と呼ばれます。

JS 相互運用の詳細なガイダンスについては、後の記事で説明されています。

Note

JavaScript の [JSImport]/[JSExport] 相互運用 API は、.NET 7 以降の ASP.NET Core のクライアント側コンポーネントで使用できます。

詳細については、「ASP.NET Core Blazor を使用した JavaScript JSImport/JSExport 相互運用」を参照してください。

信頼されていないデータを含む対話型サーバー コンポーネントの圧縮

[!警告>] 既定で有効になっている圧縮を使って、信頼されていないソースからのデータをレンダリングする、セキュリティで保護された (認証済み/承認済み) 対話型サーバー側コンポーネントは作成しないでください。 信頼されていないソースには、ルート パラメータ、クエリ文字列、JS 相互運用からのデータ、サードパーティのユーザーがコントロールできる他のデータ ソース (データベース、外部サービス) が含まれます。 詳細については、「ASP.NET Core BlazorSignalR ガイダンス」と「対話型サーバー側の ASP.NET Core Blazor レンダリングの脅威軽減策に関するガイダンス」を参照してください。

JavaScript 相互運用抽象化および機能パッケージ

@microsoft/dotnet-js-interop パッケージ (npmjs.com) (Microsoft.JSInterop NuGet パッケージ) は、.NET コードと JavaScript (JS) コード間の相互運用のための抽象化と機能を提供します。 参照ソースは dotnet/aspnetcoreGitHub リポジトリ (/src/JSInterop フォルダー) で入手できます。 詳細については、GitHub リポジトリのREADME.md ファイルを参照してください。

Note

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

TypeScript で JS 相互運用スクリプトを作成するための追加リソース:

DOM の操作

オブジェクトが Blazor と対話しない場合にのみ、JavaScript (JS) を使用して DOM を変換します。 Blazor は、DOM の表現を維持し、DOM オブジェクトと直接対話します。 Blazor によってレンダリングされた要素が JS を直接使用して、または JS 相互運用機能を使用して外部で変更された場合、DOM は Blazor の内部表現と一致しなくなり、未定義の動作が生じることがあります。 未定義の動作は、要素またはその機能の表示を妨げる​​だけでなく、アプリまたはサーバーにセキュリティ リスクをもたらす可能性もあります。

このガイダンスは、独自の JS 相互運用コードだけでなく、アプリが使用する JS ライブラリにも適用されます。これには、BootstrapJSjQuery などのサードパーティ製のフレームワークによって提供されるものも含まれます。

いくつかのドキュメントの例では、例の一部として、JS 相互運用機能を使用して要素を単なるデモンストレーションの目的で変換します。 そのような場合は、テキストに警告が表示されます。

詳しくは、「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」をご覧ください。

非同期 JavaScript 呼び出し

JS 相互運用呼び出しは、呼び出されたコードが同期であるか非同期であるかに関係なく、既定で非同期となります。 呼び出しが既定で非同期であるのは、サーバー側とクライアント側のレンダリング モデルでコンポーネントの互換性を確保するためです。 サーバー側レンダリングを採用する場合、JS 相互運用呼び出しはネットワーク接続を介して送信されるため、非同期である必要があります。 クライアント側レンダリングのみを採用するアプリの場合、同期 JS 相互運用呼び出しがサポートされます。

オブジェクトのシリアル化

Blazor では、次の要件と既定の動作でシリアル化に System.Text.Json を使用します。

  • 型には既定のコンストラクターが必要です。get/set アクセサーはパブリックである必要があります。フィールドはシリアル化されません。
  • グローバルな既定のシリアル化は、既存のコンポーネント ライブラリの破損、パフォーマンスとセキュリティへの影響、信頼性の低下を回避するためにカスタマイズできません。
  • .NET メンバー名をシリアル化すると、小文字の JSON キー名になります。
  • JSON は、大文字と小文字の混在が許可される、JsonElement C# インスタンスとして逆シリアル化されます。 C# モデル プロパティへの割り当ての内部キャストは、JSON キー名と C# プロパティ名の間に大文字と小文字の違いがあっても、期待したとおりに動作します。
  • KeyValuePair などの複雑なフレームワークの種類は発行時に IL Trimmer によってトリミングされ、JS の相互運用には存在しない可能性があります。 IL Trimmer の既定でトリミングされる種類については、カスタムの種類を作成することをお勧めします。

JsonConverter API は、カスタム シリアル化に使用できます。 プロパティに [JsonConverter] 属性の注釈を付けて、既存のデータ型の既定のシリアル化をオーバーライドできます。

詳細については、.NET ドキュメントの次のリソースを参照してください。

Blazor では、Base64 へのバイト配列のエンコードおよびデコードを回避する、最適化されたバイト配列 JS 相互運用がサポートされています。 アプリで、カスタム シリアル化を適用し、結果のバイトを渡すことができます。 詳しくは、「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」をご覧ください。

Blazor では、大量の .NET オブジェクトが急速にシリアル化される場合、または大きな .NET オブジェクトまたは多数の .NET オブジェクトをシリアル化する必要がある場合に、マーシャリングされていない JS 相互運用がサポートされます。 詳しくは、「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」をご覧ください。

コンポーネントの破棄中の DOM クリーンアップ タスク

コンポーネントの破棄の間に、DOM クリーンアップ タスクに対して JS 相互運用コードを実行しないでください。 代わりに、次の理由により、クライアント上の JavaScript (JS) で MutationObserver パターンを使用してください。

  • クリーンアップ コードが Dispose{Async} で実行されるまでに、コンポーネントが DOM から削除されている可能性があります。
  • サーバー側のレンダリング中、クリーンアップ コードが Dispose{Async} で実行されるまでに、Blazor レンダラーがフレームワークによって破棄されている可能性があります。

MutationObserver パターンを使うと、DOM から要素が削除されていても関数を実行できます。

次の例では、DOMCleanup コンポーネントは次のようになります。

  • cleanupDivid を持つ <div> が含まれています。 <div> 要素は、コンポーネントが DOM から削除されるときに、コンポーネントの残りの DOM マークアップとともに DOM から削除されます。
  • DOMCleanup.razor.js ファイルから DOMCleanupJS クラスを読み込みし、その createObserver 関数を呼び出して MutationObserver コールバックを設定します。 これらのタスクは、OnAfterRenderAsync ライフサイクル メソッド で実行されます。

DOMCleanup.razor:

@page "/dom-cleanup"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>DOM Cleanup Example</h1>

<div id="cleanupDiv"></div>

@code {
    private IJSObjectReference? module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Pages/DOMCleanup.razor.js");

            await module.InvokeVoidAsync("DOMCleanup.createObserver");
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

次の例では、DOM 変更が発生するたびに MutationObserver コールバックが実行されます。 if ステートメントによってターゲット要素 (cleanupDiv) が削除されたことが確認されたら、クリーンアップ コードを実行します (if (targetRemoved) { ... })。 クリーンアップ コードの実行後にメモリ リークを避けるために、MutationObserver を切断して削除することが重要です。

DOMCleanup.razor.js は、前述の DOMCleanup コンポーネントと並べて配置されます。

export class DOMCleanup {
  static observer;

  static createObserver() {
    const target = document.querySelector('#cleanupDiv');

    this.observer = new MutationObserver(function (mutations) {
      const targetRemoved = mutations.some(function (mutation) {
        const nodes = Array.from(mutation.removedNodes);
        return nodes.indexOf(target) !== -1;
      });

      if (targetRemoved) {
        // Cleanup resources here
        // ...

        // Disconnect and delete MutationObserver
        this.observer && this.observer.disconnect();
        delete this.observer;
      }
    });

    this.observer.observe(target.parentNode, { childList: true });
  }
}

window.DOMCleanup = DOMCleanup;

回線を使用しない JavaScript 相互運用呼び出し

このセクションはサーバー側アプリにのみ適用されます。

JavaScript (JS) 相互運用呼び出しは、SignalR 回線が切断された後は発行できません。 コンポーネントの破棄中に回線がない、または回線が存在しないその他の時点で、次のメソッド呼び出しは失敗し、回線が切断されたというメッセージが JSDisconnectedException としてログされます。

JSDisconnectedException のログを回避したり、カスタム情報をログしたりするには、try-catch ステートメントで例外をキャッチします。

次のコンポーネント破棄の例で:

  • コンポーネントでは IAsyncDisposable を実装します。
  • objInstanceIJSObjectReference です。
  • JSDisconnectedException がキャッチされ、ログはされません。
  • 必要に応じて、任意のログ レベルで catch ステートメントにカスタム情報をログできます。 次の例では、コンポーネントの破棄中にいつ、どこで回線が切断されるかを開発者が気にしないことを前提としているため、カスタム情報はログされません。
async ValueTask IAsyncDisposable.DisposeAsync()
{
    try
    {
        if (objInstance is not null)
        {
            await objInstance.DisposeAsync();
        }
    }
    catch (JSDisconnectedException)
    {
    }
}

回線が失われた後に、独自の JS オブジェクトをクリーンアップするか、クライアントで他の JS のコードを実行する必要がある場合は、クライアントの JS で MutationObserver のパターンを使用します。 MutationObserver パターンを使うと、DOM から要素が削除されていても関数を実行できます。

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

JavaScript の場所

JavaScript (JS) のコードを読み込むには、次のいずれかの方法を使用します。

警告

<script> タグは動的に更新できないため、コンポーネントが静的サーバー側レンダリング (静的 SSR) を採用することが保証されている場合にのみ、コンポーネント ファイル (.razor) に <script> タグを配置します。

警告

<script> タグは動的に更新できないため、<script> タグをコンポーネント ファイル (.razor) 内に配置しないでください。

Note

ドキュメントの例では、通常、スクリプトを <script> タグに配置するか、または外部ファイルからグローバル スクリプトを読み込みます。 これらの方法では、グローバル関数でクライアントが汚染されます。 運用アプリの場合は、必要に応じてインポートできる別の JavaScript モジュールに JavaScript を配置することをお勧めします。 詳細については、「JavaScript モジュールでの JavaScript の分離」セクションを参照してください。

Note

ドキュメントの例では、<script> タグにスクリプトを配置するか、または外部ファイルからグローバル スクリプトを読み込みます。 これらの方法では、グローバル関数でクライアントが汚染されます。 必要に応じてインポートできる別の JavaScript モジュールへの JavaScript の配置は、ASP.NET Core 5.0 より前の Blazor ではサポートされていません。 アプリで JS の分離のために JS モジュールを使用する必要がある場合は、ASP.NET Core 5.0 以降を使用してアプリをビルドすることをお勧めします。 詳細については、[バージョン] ドロップダウン リストを使用して、この記事の 5.0 以降のバージョンを選択し、「JavaScript モジュールでの JavaScript の分離」セクションを参照してください。

<head> マークアップでスクリプトを読み込む

このセクションのアプローチは、一般的には推奨されていません。

JavaScript (JS) タグ (<script>...</script>) を<head>要素マークアップに配置します。

<head>
    ...

    <script>
      window.jsMethod = (methodParameter) => {
        ...
      };
    </script>
</head>

<head> から JS を読み込むことは、次の理由により最適な方法ではありません。

  • スクリプトが Blazor に依存している場合、JS 相互運用が失敗するおそれがあります。 <head> マークアップではなく、他の方法のいずれかを使用してスクリプトを読み込むことをお勧めします。
  • スクリプト内で JS を解析するのに時間がかかるため、ページの動作が遅くなることがあります。

<body> マークアップでスクリプトを読み込む

Blazor スクリプト参照の後の終了</body>要素内に JavaScript (JS) タグ (<script>...</script>) を配置します。

<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script>
      window.jsMethod = (methodParameter) => {
        ...
      };
    </script>
</body>

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

コンポーネントと同じ場所に存在する外部 JavaScript ファイル (.js) からスクリプトを読み込む

Razor コンポーネントの JavaScript (JS) ファイルの併置は、アプリでスクリプトを整理する便利な方法です。

Blazor アプリの Razor コンポーネントは、.razor.js 拡張子を使って JS ファイルを併置し、プロジェクト内のファイルへのパスを使ってパブリックにアドレス指定できます。

{PATH}/{COMPONENT}.{EXTENSION}.js

  • {PATH} プレースホルダーは、コンポーネントへのパスです。
  • {COMPONENT} プレースホルダーはコンポーネントです。
  • {EXTENSION} プレースホルダーは、コンポーネントの拡張子 (razor) と一致します。

アプリが公開されると、スクリプトはフレームワークによって Web ルートに自動的に移動されます。 スクリプトは、bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/Pages/{COMPONENT}.razor.js に移動されます。プレースホルダーの内容は次のとおりです。

公開される静的資産への JS ファイルの配置は Blazor によって自動的に処理されるので、スクリプトの相対 URL を変更する必要はありません。

このセクションと以下の例では、主に JS ファイルの併置について説明することに重点を置きます。 最初に、通常の JS 関数で併置される JS ファイルの例を示します。 次に、モジュールを使って関数を読み込む例を示します。これは、ほとんどの運用アプリに推奨されるアプローチです。 .NET からの JS の呼び出しについては「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」で詳細に説明されており、そこに BlazorJS API のさらに詳しい説明と他の例があります。 2 番目の例で示されているコンポーネントの破棄については、「ASP.NET Core Razor コンポーネントのライフサイクル」で説明されています。

次の JsCollocation1 コンポーネントでは、HeadContent コンポーネントを介してスクリプトを読み込み、IJSRuntime.InvokeAsync を使って JS 関数を呼び出しています。 {PATH} プレースホルダーは、コンポーネントへのパスです。

重要

テスト アプリで実際に次のコードを使ってみる場合は、{PATH} プレースホルダーをコンポーネントのパスに変更してください (例: .NET 8 以降の場合は Components/Pages、.NET 7 以前の場合は Pages)。 Blazor Web アプリ (.NET 8 以降) のコンポーネントでは、対話型レンダリング モードをアプリにグローバルに、またはコンポーネント定義に適用する必要があります。

Blazor スクリプト (Blazor 開始スクリプトの場所) の後に次のスクリプトを追加します。

<script src="{PATH}/JsCollocation1.razor.js"></script>

JsCollocation1 コンポーネント ({PATH}/JsCollocation1.razor):

@page "/js-collocation-1"
@inject IJSRuntime JS

<PageTitle>JS Collocation 1</PageTitle>

<h1>JS Collocation Example 1</h1>

<button @onclick="ShowPrompt">Call showPrompt1</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private string? result;

    public async void ShowPrompt()
    {
        result = await JS.InvokeAsync<string>(
            "showPrompt1", "What's your name?");
        StateHasChanged();
    }
}

併置される JS ファイルは、JsCollocation1.razor.js というファイル名で JsCollocation1 コンポーネント ファイルに隣接して配置されます。 JsCollocation1 コンポーネント内では、スクリプトは併置されたファイルのパスで参照されます。 次の例の showPrompt1 関数は、Window prompt() からユーザーの名前を受け取り、それを表示するために JsCollocation1 コンポーネントに返します。

{PATH}/JsCollocation1.razor.js:

function showPrompt1(message) {
  return prompt(message, 'Type your name here');
}

上記の方法は、グローバル関数でクライアントを汚染するため、運用アプリでの一般的な使用には推奨されません。 運用アプリのためのさらに優れたアプローチは、JS モジュールを使うことです。 次の例で示すように、併置された JS ファイルからの JS モジュールの読み込みにも同じ一般的な原則が適用されます。

次の JsCollocation2 コンポーネントの OnAfterRenderAsync メソッドは、コンポーネント クラスの IJSObjectReference である moduleに JS モジュールを読み込みます。 module は、showPrompt2 関数を呼び出すために使われます。 {PATH} プレースホルダーは、コンポーネントへのパスです。

重要

テスト アプリで実際に次のコードを使ってみる場合は、{PATH} プレースホルダーをコンポーネントのパスに変更してください。 Blazor Web アプリ (.NET 8 以降) のコンポーネントでは、対話型レンダリング モードをアプリにグローバルに、またはコンポーネント定義に適用する必要があります。

JsCollocation2 コンポーネント ({PATH}/JsCollocation2.razor):

@page "/js-collocation-2"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>JS Collocation 2</PageTitle>

<h1>JS Collocation Example 2</h1>

<button @onclick="ShowPrompt">Call showPrompt2</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private IJSObjectReference? module;
    private string? result;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            /*
                Change the {PATH} placeholder in the next line to the path of
                the collocated JS file in the app. Examples:

                ./Components/Pages/JsCollocation2.razor.js (.NET 8 or later)
                ./Pages/JsCollocation2.razor.js (.NET 7 or earlier)
            */
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./{PATH}/JsCollocation2.razor.js");
        }
    }

    public async void ShowPrompt()
    {
        if (module is not null)
        {
            result = await module.InvokeAsync<string>(
                "showPrompt2", "What's your name?");
            StateHasChanged();
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

{PATH}/JsCollocation2.razor.js:

export function showPrompt2(message) {
  return prompt(message, 'Type your name here');
}

Razor クラス ライブラリ (RCL) によって提供されるスクリプトまたはモジュールの場合は、次のパスが使われます。

_content/{PACKAGE ID}/{PATH}/{COMPONENT}.{EXTENSION}.js

  • {PACKAGE ID} プレースホルダーは、RCL のパッケージ識別子 (または、アプリによって参照されるクラス ライブラリのライブラリ名) です。
  • {PATH} プレースホルダーは、コンポーネントへのパスです。 Razor コンポーネントが RCL のルートにある場合、パス セグメントは含まれません。
  • {COMPONENT} プレースホルダーはコンポーネント名です。
  • {EXTENSION} プレースホルダーは、コンポーネントの拡張子 (razor または cshtml) と一致します。

次の Blazor アプリの例の場合:

  • RCL のパッケージ識別子は AppJS です。
  • モジュールのスクリプトは、JsCollocation3 コンポーネント (JsCollocation3.razor) に対して読み込まれます。
  • JsCollocation3 コンポーネントは、RCL の Components/Pages フォルダーにあります。
module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./_content/AppJS/Components/Pages/JsCollocation3.razor.js");

RCL の詳細については、「ASP.NET Core Razor コンポーネントを Razor クラス ライブラリから使用する」を参照してください。

外部 JavaScript ファイル (.js) からスクリプトを読み込む

Blazor スクリプト参照の後の終了</body>要素内に、スクリプト ソース (src) パスを使用して JavaScript (JS) のタグ (<script>...</script>) を配置します。

<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script src="{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>

前の例の場合:

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

上記の <script> タグの次の例では、scripts.js ファイルはアプリの wwwroot/js フォルダーにあります。

<script src="js/scripts.js"></script>

すべてのスクリプトを wwwroot の下の別のフォルダーに保存したくない場合は、wwwroot フォルダーから直接スクリプトを提供することもできます。

<script src="scripts.js"></script>

Razor クラス ライブラリによって外部の JS ファイルが提供される場合は、安定した静的 Web アセット パス ./_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)} を使用して JS ファイルを指定します。

  • JS ファイルへの正しい静的アセット パスを作成するためには、現在のディレクトリ (./) に対するパス セグメントが必要です。
  • {PACKAGE ID} プレースホルダーは、ライブラリのパッケージ ID です。 プロジェクト ファイルで <PackageId> が指定されていない場合、パッケージ ID の既定値はプロジェクトのアセンブリ名になります。
  • {SCRIPT PATH AND FILE NAME (.js)} プレースホルダーは、wwwroot の下のパスとファイル名です。
<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script src="./_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>

上記の <script> タグの例を次に示します。

  • Razor クラス ライブラリのアセンブリ名は ComponentLibrary であり、<PackageId> はライブラリのプロジェクト ファイルで指定されません。
  • scripts.js ファイルは、クラス ライブラリの wwwroot フォルダーにあります。
<script src="./_content/ComponentLibrary/scripts.js"></script>

詳細については、「ASP.NET Core Razor コンポーネントを Razor クラス ライブラリから使用する」を参照してください。

Blazor の開始前または開始後にスクリプトを挿入する

Blazor の開始前または開始後にスクリプトが確実に読み込まれるようにするには、JavaScript 初期化子を使用します。 詳細と例については、「ASP.NET Core のBlazor起動」を参照してください。

Blazor の開始後にスクリプトを挿入する

Blazor の開始後にスクリプトを挿入するには、Blazor を手動で開始した結果の Promise にチェーンします。 詳細と例については、「ASP.NET Core のBlazor起動」を参照してください。

JavaScript モジュールでの JavaScript の分離

Blazor では、標準の Blazorに JavaScript (JS) を分離できます (JS)。

JS を分離すると、次のようなベネフィットがあります。

  • インポートされる JS によって、グローバル名前空間が汚染されなくなります。
  • ライブラリおよびコンポーネントのコンシューマーは、関連する JS をインポートする必要がありません。

詳しくは、「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」をご覧ください。

import() 演算子を使用した動的インポートは、ASP.NET Core と Blazorでサポートされています。

if ({CONDITION}) import("/additionalModule.js");

前述の例では、プレースホルダー {CONDITION} は、モジュールを読み込む必要があるかどうかを判断するための条件付きチェックを表しています。

ブラウザーの互換性については、「Can I use: JavaScript modules: dynamic import (使用できるかどうか: JavaScript モジュール: dynamic import)」を参照してください。

キャッシュされた JavaScript ファイル

JavaScript (JS) ファイルおよびその他の静的資産は、通常、Development 環境での開発中にクライアントにキャッシュされません。 開発中、静的資産要求には、値が no-cacheCache-Control ヘッダー、または値がゼロ (0) の max-age が含まれます。

Production 環境での運用中は、通常、JS ファイルはクライアントによってキャッシュされます。

ブラウザーでクライアント側のキャッシュを無効にするには、通常、開発者は次のいずれかのアプローチを採用します。

  • ブラウザーの開発者ツール コンソールが開いているときにキャッシュを無効にします。 ガイダンスについては、各ブラウザー メンテナンス ツールの開発者ツール ドキュメントを参照してください。
  • Blazor アプリの Web ページをブラウザーで手動で更新して、サーバーから JS ファイルを再読み込みします。 ASP.NET Core の HTTP キャッシング ミドルウェアでは、クライアントによって送信された有効なキャッシュなし Cache-Control ヘッダーが常に優先されます。

詳細については、以下を参照してください:

JavaScript 相互運用呼び出しのサイズ制限

このセクションは、サーバー側アプリの対話型コンポーネントにのみ適用されます。 クライアント側コンポーネントの場合、フレームワークは JavaScript (JS) 相互運用入力および出力のサイズに制限を課しません。

サーバー側アプリの対話型コンポーネントの場合、クライアントからサーバーにデータを渡す JS 相互運用呼び出しのサイズは、ハブ メソッドに許可される受信 SignalR メッセージの最大サイズによって制限され、これは HubOptions.MaximumReceiveMessageSize によって強制されます (既定値: 32 KB)。 JS から .NET への SignalR メッセージが MaximumReceiveMessageSize より大きい場合は、エラーがスローされます。 このフレームワークでは、ハブからクライアントへの SignalR メッセージのサイズが制限されることはありません。 サイズ制限、エラー メッセージ、メッセージ サイズ制限に対処するためのガイダンスの詳細については、「ASP.NET Core BlazorSignalRガイダンス」を参照してください。

アプリが実行されている場所を決定する

アプリが JS 相互運用呼び出しでコードが実行されている場所を知る必要がある場合は、OperatingSystem.IsBrowser を使用して WebAssembly 上のブラウザーのコンテキストでコンポーネントが実行されているかどうかを判断します。