ASP.NET Core Blazor の起動
この記事では、Blazor 起動を構成する方法について説明します。
Blazor 起動プロセスは、スクリプト (Blazor) blazor.{server|webassembly}.js
を介して自動かつ非同期に行われます。ここで、{server|webassembly}
プレースホルダーは Blazor Server の場合は server
、Blazor WebAssembly の場合は webassembly
です。 Blazor<script>
タグは、Blazor WebAssembly アプリの wwwroot/index.html
ファイルまたはBlazor Server アプリの Pages/_Host.cshtml
ファイルにあります。
Blazor 起動プロセスは、スクリプト (Blazor) blazor.{server|webassembly}.js
を介して自動かつ非同期に行われます。ここで、{server|webassembly}
プレースホルダーは Blazor Server の場合は server
、Blazor WebAssembly の場合は webassembly
です。 Blazor<script>
タグは、Blazor WebAssembly アプリの wwwroot/index.html
ファイルまたはBlazor Server アプリの Pages/_Layout.cshtml
ファイルにあります。
Blazor 起動プロセスは、スクリプト (Blazor) blazor.{server|webassembly}.js
を介して自動かつ非同期に行われます。ここで、{server|webassembly}
プレースホルダーは Blazor Server の場合は server
、Blazor WebAssembly の場合は webassembly
です。 Blazor<script>
タグは、Blazor WebAssembly アプリの wwwroot/index.html
ファイルまたはBlazor Server アプリの Pages/_Host.cshtml
ファイルにあります。
Blazor を手動で開始するには:
autostart="false"
属性と値を Blazor<script>
タグに追加します。Blazor.start()
を呼び出すスクリプトを、Blazor<script>
タグの後の終了</body>
タグ内に配置します。
JavaScript イニシャライザー
JavaScript (JS) イニシャライザーによって、Blazor アプリの読み込みの前後にロジックが実行されます。 JS イニシャライザーは、次のシナリオで役に立ちます。
- Blazor アプリの読み込み方法のカスタマイズ。
- Blazor 開始前のライブラリの初期化。
- Blazor の設定の構成。
JS イニシャライザーは、ビルド処理の一部として検出されて、Blazor アプリに自動的にインポートされます。 多くの場合、JS イニシャライザーを使用すると、Razor クラス ライブラリ (RCL) を使用するときにアプリからスクリプト関数を手動でトリガーする必要がなくなります。
JS イニシャライザーを定義するには、JS モジュールを {NAME}.lib.module.js
という名前のプロジェクトに追加します。{NAME}
プレースホルダーは、アセンブリ名、ライブラリ名、またはパッケージ識別子です。 ファイルをプロジェクトの Web ルートに配置します。通常、これは wwwroot
フォルダーです。
そのモジュールで、次の従来の関数のいずれかまたは両方をエクスポートします。
beforeStart(options, extensions)
: Blazor が開始する前に呼び出されます。 たとえば、beforeStart
は、読み込みプロセス、ログ レベル、およびホスティング モデルに固有のその他のオプションをカスタマイズするために使用されます。- Blazor WebAssembly の場合、
beforeStart
は、発行中に追加される Blazor WebAssembly のオプション (このセクションの例ではoptions
) と拡張機能 (このセクションの例ではextensions
) を受け取ります。 たとえば、オプションによってカスタムのブート リソース ローダーの使用を指定できます。 - Blazor Server の場合、
beforeStart
は SignalR 回線開始オプション (このセクションの例ではoptions
) を受け取ります。 BlazorWebViews
では、オプションは渡されません。
- Blazor WebAssembly の場合、
afterStarted
: Blazor が JS からの呼び出しを受け取れる状態になった後で呼び出されます。 たとえば、afterStarted
は、JS 相互運用呼び出しを行い、カスタム要素を登録することによって、ライブラリを初期化するために使用されます。afterStarted
には、Blazor インスタンスが引数として渡されます (このセクションの例ではblazor
)。
ファイル名については、次のようにします。
- JS イニシャライザーがプロジェクトの静的アセットとして使われる場合は、
{ASSEMBLY NAME}.lib.module.js
という形式を使います。{ASSEMBLY NAME}
プレースホルダーはアプリのアセンブリ名です。 たとえば、プロジェクトのアセンブリ名がBlazorSample
である場合は、ファイルをBlazorSample.lib.module.js
という名前にします。 ファイルをアプリのwwwroot
フォルダーに配置します。 - JS イニシャライザーが RCL から使われる場合は、
{LIBRARY NAME/PACKAGE ID}.lib.module.js
という形式を使います。{LIBRARY NAME/PACKAGE ID}
プレースホルダーは、プロジェクトのライブラリ名またはパッケージ識別子です。 たとえば、RCL のパッケージ識別子がRazorClassLibrary1
である場合は、ファイルをRazorClassLibrary1.lib.module.js
という名前にします。 ファイルをライブラリのwwwroot
フォルダーに配置します。
次に示すのは、beforeStart
と afterStarted
の <head>
に追加することで、Blazor が開始される前と後にカスタム スクリプトが読み込まれる JS イニシャライザーの例です。
export function beforeStart(options, extensions) {
var customScript = document.createElement('script');
customScript.setAttribute('src', 'beforeStartScripts.js');
document.head.appendChild(customScript);
}
export function afterStarted(blazor) {
var customScript = document.createElement('script');
customScript.setAttribute('src', 'afterStartedScripts.js');
document.head.appendChild(customScript);
}
前述の beforeStart
の例では、Blazor の開始前にカスタム スクリプトが読み込まれることのみが保証されています。 スクリプトで待機中の Promise の実行が Blazor の開始前に完了することは保証されません。
Note
MVC および Razor Pages アプリでは、JS イニシャライザーは自動的に読み込まれません。 ただし、アプリのマニフェストをフェッチして、JS イニシャライザーの読み込みをトリガーするスクリプトを、開発者コードに含めることができます。
JS イニシャライザーの例については、次のリソースを参照してください。
- JavaScript アプリと SPA フレームワークで Razor コンポーネントを使用する ("
quoteContainer2
の例") - ASP.NET Core の Blazor イベントの処理 ("カスタム クリップボード貼り付けイベントの例")
- ASP.NET Core Blazor WebAssembly アプリの展開レイアウト
- ASP.NET Core GitHub リポジトリ内の基本的なテスト アプリ (
BasicTestApp.lib.module.js
)
注意
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
ライブラリが特定の順序で読み込まれるようにする
カスタム スクリプトを、読み込む必要がある順序で beforeStart
と afterStarted
の <head>
に追加します。
次の例では、script2.js
の前に script1.js
、script4.js
の前に script3.js
を読み込みます。
export function beforeStart(options, extensions) {
var customScript1 = document.createElement('script');
customScript1.setAttribute('src', 'script1.js');
document.head.appendChild(customScript1);
var customScript2 = document.createElement('script');
customScript2.setAttribute('src', 'script2.js');
document.head.appendChild(customScript2);
}
export function afterStarted(blazor) {
var customScript1 = document.createElement('script');
customScript1.setAttribute('src', 'script3.js');
document.head.appendChild(customScript1);
var customScript2 = document.createElement('script');
customScript2.setAttribute('src', 'script4.js');
document.head.appendChild(customScript2);
}
追加のモジュールをインポートする
JS の初期化子ファイル (*.lib.module.js
) で最上位の import
ステートメントを使用して、追加のモジュールをインポートします。
additionalModule.js
:
export function logMessage() {
console.log('logMessage is logging');
}
import { logMessage } from "/additionalModule.js";
export function beforeStart(options, extensions) {
...
logMessage();
}
マップをインポートする
マップのインポートは、ASP.NET Core と Blazor でサポートされています。
ドキュメントの準備完了時に Blazor を初期化する
次の例では、ドキュメントの準備が整うと Blazor が起動されます。
<body>
...
<script src="_framework/blazor.{server|webassembly}.js" autostart="false"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
Blazor.start();
});
</script>
</body>
前述のマークアップの {server|webassembly}
プレースホルダーは、Blazor Server アプリの場合は server
、Blazor WebAssembly アプリの場合は webassembly
です。
手動で起動した結果として得た Promise
に連結する
JS 相互運用の初期化など、追加のタスクを実行するには、then
を使用して、手動で Blazor アプリを起動させた結果として得た Promise
に連結します。
<body>
...
<script src="_framework/blazor.{server|webassembly}.js" autostart="false"></script>
<script>
Blazor.start().then(function () {
...
});
</script>
</body>
前述のマークアップの {server|webassembly}
プレースホルダーは、Blazor Server アプリの場合は server
、Blazor WebAssembly アプリの場合は webassembly
です。
Note
Blazor の開始後にライブラリで追加のタスクを自動的に実行するには、JavaScript イニシャライザーを使います。 JS イニシャライザーを使う場合は、ライブラリのコンシューマーが JS の呼び出しを Blazor の手動起動にチェーンする必要はありません。
ブート リソースを読み込む
"このセクションは Blazor WebAssembly アプリにのみ適用されます。 "
Blazor WebAssembly アプリがブラウザーに読み込まれると、アプリによってサーバーから次のブート リソースがダウンロードされます。
- アプリをブートストラップする JavaScript コード
- .NET ランタイムとアセンブリ
- ロケール固有のデータ
loadBootResource
API を使用して、これらのブート リソースの読み込み方法をカスタマイズします。 loadBootResource
関数によって、組み込みのブート リソース読み込みメカニズムをオーバーライドします。 次のシナリオで loadBootResource
を使用します。
- タイムゾーン データや
dotnet.wasm
などの静的なリソースを、CDN から読み込む。 - HTTP 要求を使用して圧縮されたアセンブリを読み込み、サーバーからの圧縮コンテンツのフェッチをサポートしていないホストのクライアントに展開する。
- 各
fetch
要求を新しい名前にリダイレクトして、リソースを別の名前に設定する。
Note
外部ソースは、ブラウザーがクロスオリジンのリソースの読み込みを許可するために必要なクロス オリジン リソース共有 (CORS) ヘッダーを返す必要があります。 通常、既定では、必要なヘッダーが CDN によって提供されます。
loadBootResource
パラメーターは次の表に表示されます。
パラメーター | 説明 |
---|---|
type |
リソースの型。 許容される型としては、assembly 、pdb 、dotnetjs 、dotnetwasm 、および timezonedata があります。 カスタム動作の型のみ指定する必要があります。 loadBootResource に指定されていない型は、既定の読み込み動作に従ってフレームワークによって読み込まれます。 |
name |
リソースの名前。 |
defaultUri |
リソースの相対 URI または絶対 URI。 |
integrity |
応答で予想されるコンテンツを表す整合性文字列。 |
loadBootResource
関数では、URI 文字列を返して、読み込みプロセスをオーバーライドできます。 次の例では、bin/Release/net5.0/wwwroot/_framework
からの次のファイルは https://cdn.example.com/blazorwebassembly/5.0.0/
の CDN から提供されます。
dotnet.*.js
dotnet.wasm
- タイムゾーン データ
wwwroot/index.html
の終了 </body>
タグ内:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
Blazor.start({
loadBootResource: function (type, name, defaultUri, integrity) {
console.log(`Loading: '${type}', '${name}', '${defaultUri}', '${integrity}'`);
switch (type) {
case 'dotnetjs':
case 'dotnetwasm':
case 'timezonedata':
return `https://cdn.example.com/blazorwebassembly/5.0.0/${name}`;
}
}
});
</script>
ブート リソースの URL 以外のものをカスタマイズするには、loadBootResource
関数から fetch
を直接呼び出して、結果を返すことができます。 次の例では、カスタム HTTP ヘッダーを送信要求に追加します。 既定の整合性チェックの動作を保持するため、integrity
パラメーターを渡します。
wwwroot/index.html
の終了 </body>
タグ内:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
Blazor.start({
loadBootResource: function (type, name, defaultUri, integrity) {
return fetch(defaultUri, {
cache: 'no-cache',
integrity: integrity,
headers: { 'Custom-Header': 'Custom Value' }
});
}
});
</script>
loadBootResource
関数では、次を返すこともできます。
null
/undefined
。既定の読み込み動作になります。Response
promise。 例については、「ASP.NET Core Blazor WebAssembly のホストと展開」をご覧ください。
C# コードでヘッダーを制御する
C# コードで起動時にヘッダーを制御するには、次の方法を使用します。
次の例では、コンテンツ セキュリティ ポリシー (CSP) ヘッダーによって CSP がアプリに適用されます。 {POLICY STRING}
プレースホルダーは、CSP ポリシーの文字列です。
- Blazor Server アプリとプリレンダリング済み Blazor WebAssembly アプリでは、ASP.NET Core ミドルウェアがヘッダー コレクションの制御に使用されます。
Program.cs
:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy", "{POLICY STRING}");
await next();
});
Startup.cs
の Startup.Configure
で:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy", "{POLICY STRING}");
await next();
});
前の例ではインライン ミドルウェアを使用していますが、カスタム ミドルウェア クラスを作成し、Program.cs
で拡張メソッドを使用してミドルウェアを呼び出すこともできます。 詳細については、「カスタム ASP.NET Core ミドルウェアを記述する」を参照してください。
- プリレンダリングされていないホストされた Blazor WebAssembly アプリでは、OnPrepareResponse ステージでの応答ヘッダーを指定する StaticFileOptions を MapFallbackToFile に渡します。
Server プロジェクトの Program.cs
:
var staticFileOptions = new StaticFileOptions
{
OnPrepareResponse = context =>
{
context.Context.Response.Headers.Add("Content-Security-Policy",
"{POLICY STRING}");
}
};
...
app.MapFallbackToFile("index.html", staticFileOptions);
Server プロジェクトの Startup.Configure
(Startup.cs
):
var staticFileOptions = new StaticFileOptions
{
OnPrepareResponse = context =>
{
context.Context.Response.Headers.Add("Content-Security-Policy",
"{POLICY STRING}");
}
};
...
app.MapFallbackToFile("index.html", staticFileOptions);
CSP について詳しくは、「ASP.NET Core Blazor のコンテンツ セキュリティ ポリシーを適用する」をご覧ください。
読み込みの進行状況の指標
"このセクションは アプリにのみ適用されます。 "
Blazor WebAssembly プロジェクト テンプレートには、スケーラブル ベクター グラフィックス (SVG) と、アプリの読み込みの進行状況を示すテキスト インジケーターが含まれています。
進行状況インジケーターは、Blazor WebAssembly で指定された次の 2 つの CSS カスタム プロパティ (変数) を使用して、HTML と CSS で実装されます。
--blazor-load-percentage
: 読み込まれたアプリ ファイルの割合。--blazor-load-percentage-text
: 読み込まれたアプリ ファイルの割合。最も近い整数に四捨五入されます。
上記の CSS 変数を使用して、アプリのスタイルに一致するカスタム進行状況インジケーターを作成できます。
次に例を示します。
resourcesLoaded
は、アプリの起動時に読み込まれたリソースのある時点でのカウントです。totalResources
は、読み込むリソースの合計数です。
const percentage = resourcesLoaded / totalResources * 100;
document.documentElement.style.setProperty(
'--blazor-load-percentage', `${percentage}%`);
document.documentElement.style.setProperty(
'--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`);
既定の円形進行状況インジケーターは、wwwroot/index.html
ファイル内の HTML に実装されます。
<div id="app">
<svg class="loading-progress">
<circle r="40%" cx="50%" cy="50%" />
<circle r="40%" cx="50%" cy="50%" />
</svg>
<div class="loading-progress-text"></div>
</div>
Blazor WebAssembly プロジェクト テンプレートのマークアップと既定の進行状況インジケーターのスタイルを確認するには、ASP.NET Core 参照ソースをご覧ください。
注意
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
既定の円形進行状況インジケーターを使用する代わりに、次の例では線形進行状況インジケーターを実装する方法を示します。
wwwroot/css/app.css
に次のスタイルを追加します。
.linear-progress {
background: silver;
width: 50vw;
margin: 20% auto;
height: 1rem;
border-radius: 10rem;
overflow: hidden;
position: relative;
}
.linear-progress:after {
content: '';
position: absolute;
inset: 0;
background: blue;
scale: var(--blazor-load-percentage, 0%) 100%;
transform-origin: left top;
transition: scale ease-out 0.5s;
}
CSS 変数 (var(...)
) を使用して、--blazor-load-percentage
の値を、アプリのファイルの読み込みの進行状況を示す青い擬似要素の scale
プロパティに渡します。 アプリが読み込まれると、--blazor-load-percentage
が自動的に更新され、進行状況インジケーターの視覚的表現が動的に変更されます。
wwwroot/index.html
で、<div id="app">...</div>
の既定の SVG 円形インジケーターを削除し、次のマークアップに置き換えます。
<div class="linear-progress"></div>