Improve initialization and SignalR configuration
Fixes: #6887 and #6887 and #5624 Adds support for calling Blazor.start({...}) and passing in a configuration object. For now all you can configure is the SignalR HubConnectionBuilder. This is a priority right now because we want to make configuring SignalR's logging accessible.
This commit is contained in:
parent
555b506a97
commit
f2e9ef3441
|
|
@ -2,7 +2,7 @@ import '@dotnet/jsinterop';
|
||||||
import './GlobalExports';
|
import './GlobalExports';
|
||||||
import * as signalR from '@aspnet/signalr';
|
import * as signalR from '@aspnet/signalr';
|
||||||
import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack';
|
import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack';
|
||||||
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
|
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync, shouldAutoStart } from './BootCommon';
|
||||||
import { CircuitHandler } from './Platform/Circuits/CircuitHandler';
|
import { CircuitHandler } from './Platform/Circuits/CircuitHandler';
|
||||||
import { AutoReconnectCircuitHandler } from './Platform/Circuits/AutoReconnectCircuitHandler';
|
import { AutoReconnectCircuitHandler } from './Platform/Circuits/AutoReconnectCircuitHandler';
|
||||||
import RenderQueue from './Platform/Circuits/RenderQueue';
|
import RenderQueue from './Platform/Circuits/RenderQueue';
|
||||||
|
|
@ -10,9 +10,21 @@ import { ConsoleLogger } from './Platform/Logging/Loggers';
|
||||||
import { LogLevel, ILogger } from './Platform/Logging/ILogger';
|
import { LogLevel, ILogger } from './Platform/Logging/ILogger';
|
||||||
import { discoverPrerenderedCircuits, startCircuit } from './Platform/Circuits/CircuitManager';
|
import { discoverPrerenderedCircuits, startCircuit } from './Platform/Circuits/CircuitManager';
|
||||||
|
|
||||||
let renderingFailed = false;
|
|
||||||
|
|
||||||
async function boot(): Promise<void> {
|
type SignalRBuilder = (builder: signalR.HubConnectionBuilder) => void;
|
||||||
|
interface BlazorOptions {
|
||||||
|
configureSignalR?: SignalRBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
|
let renderingFailed = false;
|
||||||
|
let started = false;
|
||||||
|
|
||||||
|
async function boot(options?: BlazorOptions): Promise<void> {
|
||||||
|
|
||||||
|
if (started) {
|
||||||
|
throw new Error('Blazor has already started.');
|
||||||
|
}
|
||||||
|
started = true;
|
||||||
|
|
||||||
// For development.
|
// For development.
|
||||||
// Simply put a break point here and modify the log level during
|
// Simply put a break point here and modify the log level during
|
||||||
|
|
@ -30,7 +42,9 @@ async function boot(): Promise<void> {
|
||||||
return loadEmbeddedResourcesAsync(bootConfig);
|
return loadEmbeddedResourcesAsync(bootConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialConnection = await initializeConnection(circuitHandlers, logger);
|
// pass options.configureSignalR to configure the signalR.HubConnectionBuilder
|
||||||
|
const configureSignalR = (options && options.configureSignalR) || null;
|
||||||
|
const initialConnection = await initializeConnection(configureSignalR, circuitHandlers, logger);
|
||||||
|
|
||||||
const circuits = discoverPrerenderedCircuits(document);
|
const circuits = discoverPrerenderedCircuits(document);
|
||||||
for (let i = 0; i < circuits.length; i++) {
|
for (let i = 0; i < circuits.length; i++) {
|
||||||
|
|
@ -55,7 +69,7 @@ async function boot(): Promise<void> {
|
||||||
// We can't reconnect after a failure, so exit early.
|
// We can't reconnect after a failure, so exit early.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const reconnection = await initializeConnection(circuitHandlers, logger);
|
const reconnection = await initializeConnection(configureSignalR, circuitHandlers, logger);
|
||||||
const results = await Promise.all(circuits.map(circuit => circuit.reconnect(reconnection)));
|
const results = await Promise.all(circuits.map(circuit => circuit.reconnect(reconnection)));
|
||||||
|
|
||||||
if (reconnectionFailed(results)) {
|
if (reconnectionFailed(results)) {
|
||||||
|
|
@ -81,14 +95,20 @@ async function boot(): Promise<void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initializeConnection(circuitHandlers: CircuitHandler[], logger: ILogger): Promise<signalR.HubConnection> {
|
async function initializeConnection(configureSignalR: SignalRBuilder | null, circuitHandlers: CircuitHandler[], logger: ILogger): Promise<signalR.HubConnection> {
|
||||||
|
|
||||||
const hubProtocol = new MessagePackHubProtocol();
|
const hubProtocol = new MessagePackHubProtocol();
|
||||||
(hubProtocol as any).name = 'blazorpack';
|
(hubProtocol as any).name = 'blazorpack';
|
||||||
const connection = new signalR.HubConnectionBuilder()
|
|
||||||
|
const connectionBuilder = new signalR.HubConnectionBuilder()
|
||||||
.withUrl('_blazor')
|
.withUrl('_blazor')
|
||||||
.withHubProtocol(hubProtocol)
|
.withHubProtocol(hubProtocol);
|
||||||
.configureLogging(signalR.LogLevel.Information)
|
|
||||||
.build();
|
if (configureSignalR) {
|
||||||
|
configureSignalR(connectionBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = connectionBuilder.build();
|
||||||
|
|
||||||
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
|
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
|
||||||
connection.on('JS.RenderBatch', (browserRendererId: number, batchId: number, batchData: Uint8Array) => {
|
connection.on('JS.RenderBatch', (browserRendererId: number, batchId: number, batchData: Uint8Array) => {
|
||||||
|
|
@ -131,4 +151,7 @@ function unhandledError(connection: signalR.HubConnection, err: Error, logger: I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boot();
|
window['Blazor'].start = boot;
|
||||||
|
if (shouldAutoStart()) {
|
||||||
|
boot();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,17 @@ import { getAssemblyNameFromUrl } from './Platform/Url';
|
||||||
import { renderBatch } from './Rendering/Renderer';
|
import { renderBatch } from './Rendering/Renderer';
|
||||||
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
|
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
|
||||||
import { Pointer } from './Platform/Platform';
|
import { Pointer } from './Platform/Platform';
|
||||||
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
|
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync, shouldAutoStart } from './BootCommon';
|
||||||
|
|
||||||
|
let started = false;
|
||||||
|
|
||||||
|
async function boot(options?: any) {
|
||||||
|
|
||||||
|
if (started) {
|
||||||
|
throw new Error('Blazor has already started.');
|
||||||
|
}
|
||||||
|
started = true;
|
||||||
|
|
||||||
async function boot() {
|
|
||||||
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
|
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
|
||||||
const platform = Environment.setPlatform(monoPlatform);
|
const platform = Environment.setPlatform(monoPlatform);
|
||||||
window['Blazor'].platform = platform;
|
window['Blazor'].platform = platform;
|
||||||
|
|
@ -43,4 +51,7 @@ async function boot() {
|
||||||
platform.callEntryPoint(mainAssemblyName, bootConfig.entryPoint, []);
|
platform.callEntryPoint(mainAssemblyName, bootConfig.entryPoint, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
boot();
|
window['Blazor'].start = boot;
|
||||||
|
if (shouldAutoStart()) {
|
||||||
|
boot();
|
||||||
|
}
|
||||||
|
|
@ -37,3 +37,10 @@ interface BootJsonData {
|
||||||
jsReferences: string[];
|
jsReferences: string[];
|
||||||
linkerEnabled: boolean;
|
linkerEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tells you if the script was added without <script src="..." autostart="false"></script>
|
||||||
|
export function shouldAutoStart() {
|
||||||
|
return document &&
|
||||||
|
document.currentScript &&
|
||||||
|
document.currentScript.getAttribute('autostart') !== 'false';
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { platform } from './Environment';
|
|
||||||
import { navigateTo, internalFunctions as uriHelperInternalFunctions } from './Services/UriHelper';
|
import { navigateTo, internalFunctions as uriHelperInternalFunctions } from './Services/UriHelper';
|
||||||
import { internalFunctions as httpInternalFunctions } from './Services/Http';
|
import { internalFunctions as httpInternalFunctions } from './Services/Http';
|
||||||
import { attachRootComponentToElement } from './Rendering/Renderer';
|
import { attachRootComponentToElement } from './Rendering/Renderer';
|
||||||
import { Pointer } from './Platform/Platform';
|
|
||||||
|
|
||||||
// Make the following APIs available in global scope for invocation from JS
|
// Make the following APIs available in global scope for invocation from JS
|
||||||
window['Blazor'] = {
|
window['Blazor'] = {
|
||||||
|
|
@ -13,4 +11,4 @@ window['Blazor'] = {
|
||||||
http: httpInternalFunctions,
|
http: httpInternalFunctions,
|
||||||
uriHelper: uriHelperInternalFunctions
|
uriHelper: uriHelperInternalFunctions
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -210,6 +210,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
..\..\.editorconfig = ..\..\.editorconfig
|
..\..\.editorconfig = ..\..\.editorconfig
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Components.Prerendering", "..\Mvc\Mvc.Components.Prerendering\src\Microsoft.AspNetCore.Mvc.Components.Prerendering.csproj", "{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -1324,6 +1326,18 @@ Global
|
||||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x64.Build.0 = Debug|Any CPU
|
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x64.Build.0 = Debug|Any CPU
|
||||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.ActiveCfg = Debug|Any CPU
|
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.ActiveCfg = Debug|Any CPU
|
||||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.Build.0 = Debug|Any CPU
|
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -1423,6 +1437,7 @@ Global
|
||||||
{04262990-929C-42BF-85A9-21C25FA95617} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
{04262990-929C-42BF-85A9-21C25FA95617} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||||
{DC47C40A-FC38-44E4-94A4-ADE794E76309} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
{DC47C40A-FC38-44E4-94A4-ADE794E76309} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
{9088E4E4-B855-457F-AE9E-D86709A5E1F4} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||||
|
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE}
|
SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Basic test app</title>
|
<title>Basic test app</title>
|
||||||
<base href="/subdir/" />
|
<base href="/subdir/" />
|
||||||
<link href="style.css" rel="stylesheet" />
|
<link href="style.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,13 @@
|
||||||
|
|
||||||
<app>@(await Html.RenderComponentAsync<App>(new { Name="Guest" }))</app>
|
<app>@(await Html.RenderComponentAsync<App>(new { Name="Guest" }))</app>
|
||||||
|
|
||||||
<script src="_framework/components.server.js"></script>
|
<script src="_framework/components.server.js" autostart="false"></script>
|
||||||
|
<script>
|
||||||
|
Blazor.start({
|
||||||
|
configureSignalR: function (builder) {
|
||||||
|
builder.configureLogging(2); // LogLevel.Information
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,11 @@
|
||||||
interactive states, we only load the .js file when told to.
|
interactive states, we only load the .js file when told to.
|
||||||
*@
|
*@
|
||||||
<hr />
|
<hr />
|
||||||
<button id="load-boot-script" onclick="loadBootScript(event)">Load boot script</button>
|
|
||||||
<script>
|
|
||||||
function loadBootScript(event) {
|
|
||||||
event.srcElement.disabled = true;
|
|
||||||
var scriptElem = document.createElement('script');
|
|
||||||
scriptElem.src = '_framework/components.server.js';
|
|
||||||
document.body.appendChild(scriptElem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<button id="load-boot-script" onclick="Blazor.start()">Load boot script</button>
|
||||||
|
|
||||||
|
<script src="_framework/components.server.js" autostart="false"></script>
|
||||||
|
<script>
|
||||||
// Used by InteropOnInitializationComponent
|
// Used by InteropOnInitializationComponent
|
||||||
function setElementValue(element, newValue) {
|
function setElementValue(element, newValue) {
|
||||||
element.value = newValue;
|
element.value = newValue;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue