次の方法で共有


ASP.NET Core Blazor アプリでの JavaScript の場所

Note

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

警告

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

重要

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

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

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

<script> タグの場所

<script> タグは動的に更新できないため、コンポーネントが.razor を採用することが保証されている場合にのみ、コンポーネント ファイル () に <script> タグを配置します。 コンポーネント ファイルに <script> タグを配置してもコンパイル時の警告やエラーは発生しませんが、コンポーネントのレンダリング時に静的 SSR を採用しないコンポーネントでは、スクリプトの読み込み動作が期待と一致しない可能性があります。

<script> タグは動的に更新できないため、.razor タグをコンポーネント ファイル (<script>) 内に配置しないでください。 コンポーネント ファイルに <script> タグを配置すると、コンパイル時エラーが発生します。

Note

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

Note

ドキュメントの例では、<script> タグにスクリプトを配置するか、または外部ファイルからグローバル スクリプトを読み込みます。 これらの方法では、グローバル関数でクライアントが汚染されます。 必要に応じてインポートできる別の JSへの の配置は、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>

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

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

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

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

<body>
    ...

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

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

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

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

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

{PATH}/{COMPONENT}.razor.js

  • {PATH} プレースホルダーは、コンポーネントへのパスです。
  • {COMPONENT} プレースホルダーはコンポーネントです。

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

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

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

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

重要

テスト アプリで実際に次のコードを使ってみる場合は、{PATH} プレースホルダーをコンポーネントのパスに変更してください (例: .NET 8 以降の場合は Components/Pages、.NET 7 以前の場合は Pages)。 Blazor Web App (.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 というファイル名で JsCollocation1.razor.js コンポーネント ファイルに隣接して配置されます。 JsCollocation1 コンポーネント内では、スクリプトは併置されたファイルのパスで参照されます。 次の例の showPrompt1 関数は、Window prompt() からユーザーの名前を受け取り、それを表示するために JsCollocation1 コンポーネントに返します。

{PATH}/JsCollocation1.razor.js:

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

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

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

重要

テスト アプリで実際に次のコードを使ってみる場合は、{PATH} プレースホルダーをコンポーネントのパスに変更してください。 Blazor Web App (.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)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

前の例では、JSDisconnectedExceptionのBlazor回路が失われた場合に、モジュールの破棄中にSignalRがトラップされます。 上記のコードが Blazor WebAssembly アプリで使用されている場合、失われる SignalR 接続がないため、 try-catch ブロックを削除し、モジュールを破棄する行 (await module.DisposeAsync();) のままにすることができます。 詳しくは、「ASP.NET Core Blazor JavaScript の相互運用性 (JS 相互運用)」をご覧ください。

{PATH}/JsCollocation2.razor.js:

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

JS クラス ライブラリ (RCL) での併置された Razor に対するスクリプトとモジュールの使用は、Blazor インターフェイスに基づく JS の IJSRuntime 相互運用メカニズムでのみサポートされます。 JavaScript [JSImport]/[JSExport] 相互運用を実装する場合は、「ASP.NET Core Blazor を使用した JavaScript JSImport/JSExport の相互運用」をご覧ください。

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

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

  • ./ ファイルへの正しい静的アセット パスを作成するためには、現在のディレクトリ (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) からスクリプトを読み込む

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

<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によって外部の ファイルが提供される場合は、安定した静的 Web アセット パス JS を使用して _content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.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 の開始後にスクリプトを挿入するには、Promise を手動で開始した結果の Blazor にチェーンします。 詳細と例については、「ASP.NET Core のBlazor起動」を参照してください。

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

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

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

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

サーバー側のシナリオでは、JSDisconnectedExceptionのBlazor回線が失われると、SignalR相互運用呼び出しによってモジュールが破棄されるのを防ぎ、ハンドルされない例外が発生した場合に、常にJSをトラップします。 Blazor WebAssemblyアプリは、SignalR相互運用中にJS接続を使用しないため、モジュールを破棄するためにJSDisconnectedExceptionアプリでBlazor WebAssemblyをトラップする必要はありません。

詳細については、次のリソースを参照してください。