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

Note

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

警告

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

重要

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

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

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

警告

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

警告

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

Note

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

Note

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

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

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

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

Blazor スクリプト参照の後の終了 </body> 要素内に JavaScript タグ (<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}.razor.js

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

アプリが公開されると、スクリプトはフレームワークによって Web ルートに自動的に移動されます。 スクリプトは、bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/{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 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.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 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)
        {
            await module.DisposeAsync();
        }
    }
}

{PATH}/JsCollocation2.razor.js:

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

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

IJSRuntime ベースの JS 相互運用を使用して Razor クラス ライブラリ (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) からスクリプトを読み込む

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 ファイルを指定します。

  • {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 では、標準の JS モジュールに JavaScript (JS) を分離できます (ECMAScript の仕様)。

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)」を参照してください。