Skip to content

Commit f2e9ef3

Browse files
Ryan Nowakrynowak
Ryan Nowak
authored andcommitted
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.
1 parent 555b506 commit f2e9ef3

File tree

8 files changed

+83
-27
lines changed

8 files changed

+83
-27
lines changed

src/Components/Browser.JS/src/Boot.Server.ts

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,29 @@ import '@dotnet/jsinterop';
22
import './GlobalExports';
33
import * as signalR from '@aspnet/signalr';
44
import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack';
5-
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
5+
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync, shouldAutoStart } from './BootCommon';
66
import { CircuitHandler } from './Platform/Circuits/CircuitHandler';
77
import { AutoReconnectCircuitHandler } from './Platform/Circuits/AutoReconnectCircuitHandler';
88
import RenderQueue from './Platform/Circuits/RenderQueue';
99
import { ConsoleLogger } from './Platform/Logging/Loggers';
1010
import { LogLevel, ILogger } from './Platform/Logging/ILogger';
1111
import { discoverPrerenderedCircuits, startCircuit } from './Platform/Circuits/CircuitManager';
1212

13+
14+
type SignalRBuilder = (builder: signalR.HubConnectionBuilder) => void;
15+
interface BlazorOptions {
16+
configureSignalR?: SignalRBuilder,
17+
};
18+
1319
let renderingFailed = false;
20+
let started = false;
1421

15-
async function boot(): Promise<void> {
22+
async function boot(options?: BlazorOptions): Promise<void> {
23+
24+
if (started) {
25+
throw new Error('Blazor has already started.');
26+
}
27+
started = true;
1628

1729
// For development.
1830
// Simply put a break point here and modify the log level during
@@ -30,7 +42,9 @@ async function boot(): Promise<void> {
3042
return loadEmbeddedResourcesAsync(bootConfig);
3143
});
3244

33-
const initialConnection = await initializeConnection(circuitHandlers, logger);
45+
// pass options.configureSignalR to configure the signalR.HubConnectionBuilder
46+
const configureSignalR = (options && options.configureSignalR) || null;
47+
const initialConnection = await initializeConnection(configureSignalR, circuitHandlers, logger);
3448

3549
const circuits = discoverPrerenderedCircuits(document);
3650
for (let i = 0; i < circuits.length; i++) {
@@ -55,7 +69,7 @@ async function boot(): Promise<void> {
5569
// We can't reconnect after a failure, so exit early.
5670
return false;
5771
}
58-
const reconnection = await initializeConnection(circuitHandlers, logger);
72+
const reconnection = await initializeConnection(configureSignalR, circuitHandlers, logger);
5973
const results = await Promise.all(circuits.map(circuit => circuit.reconnect(reconnection)));
6074

6175
if (reconnectionFailed(results)) {
@@ -81,14 +95,20 @@ async function boot(): Promise<void> {
8195
}
8296
}
8397

84-
async function initializeConnection(circuitHandlers: CircuitHandler[], logger: ILogger): Promise<signalR.HubConnection> {
98+
async function initializeConnection(configureSignalR: SignalRBuilder | null, circuitHandlers: CircuitHandler[], logger: ILogger): Promise<signalR.HubConnection> {
99+
85100
const hubProtocol = new MessagePackHubProtocol();
86101
(hubProtocol as any).name = 'blazorpack';
87-
const connection = new signalR.HubConnectionBuilder()
102+
103+
const connectionBuilder = new signalR.HubConnectionBuilder()
88104
.withUrl('_blazor')
89-
.withHubProtocol(hubProtocol)
90-
.configureLogging(signalR.LogLevel.Information)
91-
.build();
105+
.withHubProtocol(hubProtocol);
106+
107+
if (configureSignalR) {
108+
configureSignalR(connectionBuilder);
109+
}
110+
111+
const connection = connectionBuilder.build();
92112

93113
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
94114
connection.on('JS.RenderBatch', (browserRendererId: number, batchId: number, batchData: Uint8Array) => {
@@ -131,4 +151,7 @@ function unhandledError(connection: signalR.HubConnection, err: Error, logger: I
131151
}
132152
}
133153

134-
boot();
154+
window['Blazor'].start = boot;
155+
if (shouldAutoStart()) {
156+
boot();
157+
}

src/Components/Browser.JS/src/Boot.WebAssembly.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@ import { getAssemblyNameFromUrl } from './Platform/Url';
66
import { renderBatch } from './Rendering/Renderer';
77
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
88
import { Pointer } from './Platform/Platform';
9-
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
9+
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync, shouldAutoStart } from './BootCommon';
10+
11+
let started = false;
12+
13+
async function boot(options?: any) {
14+
15+
if (started) {
16+
throw new Error('Blazor has already started.');
17+
}
18+
started = true;
1019

11-
async function boot() {
1220
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
1321
const platform = Environment.setPlatform(monoPlatform);
1422
window['Blazor'].platform = platform;
@@ -43,4 +51,7 @@ async function boot() {
4351
platform.callEntryPoint(mainAssemblyName, bootConfig.entryPoint, []);
4452
}
4553

46-
boot();
54+
window['Blazor'].start = boot;
55+
if (shouldAutoStart()) {
56+
boot();
57+
}

src/Components/Browser.JS/src/BootCommon.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,10 @@ interface BootJsonData {
3737
jsReferences: string[];
3838
linkerEnabled: boolean;
3939
}
40+
41+
// Tells you if the script was added without <script src="..." autostart="false"></script>
42+
export function shouldAutoStart() {
43+
return document &&
44+
document.currentScript &&
45+
document.currentScript.getAttribute('autostart') !== 'false';
46+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { platform } from './Environment';
21
import { navigateTo, internalFunctions as uriHelperInternalFunctions } from './Services/UriHelper';
32
import { internalFunctions as httpInternalFunctions } from './Services/Http';
43
import { attachRootComponentToElement } from './Rendering/Renderer';
5-
import { Pointer } from './Platform/Platform';
64

75
// Make the following APIs available in global scope for invocation from JS
86
window['Blazor'] = {
@@ -13,4 +11,4 @@ window['Blazor'] = {
1311
http: httpInternalFunctions,
1412
uriHelper: uriHelperInternalFunctions
1513
}
16-
};
14+
};

src/Components/Components.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
210210
..\..\.editorconfig = ..\..\.editorconfig
211211
EndProjectSection
212212
EndProject
213+
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}"
214+
EndProject
213215
Global
214216
GlobalSection(SolutionConfigurationPlatforms) = preSolution
215217
Debug|Any CPU = Debug|Any CPU
@@ -1324,6 +1326,18 @@ Global
13241326
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x64.Build.0 = Debug|Any CPU
13251327
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.ActiveCfg = Debug|Any CPU
13261328
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.Build.0 = Debug|Any CPU
1329+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1330+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.Build.0 = Debug|Any CPU
1331+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.ActiveCfg = Debug|Any CPU
1332+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.Build.0 = Debug|Any CPU
1333+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.ActiveCfg = Debug|Any CPU
1334+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.Build.0 = Debug|Any CPU
1335+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.ActiveCfg = Release|Any CPU
1336+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.Build.0 = Release|Any CPU
1337+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.ActiveCfg = Release|Any CPU
1338+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.Build.0 = Release|Any CPU
1339+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.ActiveCfg = Release|Any CPU
1340+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.Build.0 = Release|Any CPU
13271341
EndGlobalSection
13281342
GlobalSection(SolutionProperties) = preSolution
13291343
HideSolutionNode = FALSE
@@ -1423,6 +1437,7 @@ Global
14231437
{04262990-929C-42BF-85A9-21C25FA95617} = {2FC10057-7A0A-4E34-8302-879925BC0102}
14241438
{DC47C40A-FC38-44E4-94A4-ADE794E76309} = {2FC10057-7A0A-4E34-8302-879925BC0102}
14251439
{9088E4E4-B855-457F-AE9E-D86709A5E1F4} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
1440+
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C} = {2FC10057-7A0A-4E34-8302-879925BC0102}
14261441
EndGlobalSection
14271442
GlobalSection(ExtensibilityGlobals) = postSolution
14281443
SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE}

src/Components/test/testassets/BasicTestApp/wwwroot/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8" />
55
<title>Basic test app</title>
6-
<base href="/subdir/" />
6+
<base href="/subdir/" />
77
<link href="style.css" rel="stylesheet" />
88
</head>
99
<body>

src/Components/test/testassets/ComponentsApp.Server/Pages/Index.cshtml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515

1616
<app>@(await Html.RenderComponentAsync<App>(new { Name="Guest" }))</app>
1717

18-
<script src="_framework/components.server.js"></script>
19-
18+
<script src="_framework/components.server.js" autostart="false"></script>
19+
<script>
20+
Blazor.start({
21+
configureSignalR: function (builder) {
22+
builder.configureLogging(2); // LogLevel.Information
23+
}
24+
});
25+
</script>
2026
</body>
2127
</html>

src/Components/test/testassets/TestServer/Pages/PrerenderedHost.cshtml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,11 @@
1515
interactive states, we only load the .js file when told to.
1616
*@
1717
<hr />
18-
<button id="load-boot-script" onclick="loadBootScript(event)">Load boot script</button>
19-
<script>
20-
function loadBootScript(event) {
21-
event.srcElement.disabled = true;
22-
var scriptElem = document.createElement('script');
23-
scriptElem.src = '_framework/components.server.js';
24-
document.body.appendChild(scriptElem);
25-
}
2618

19+
<button id="load-boot-script" onclick="Blazor.start()">Load boot script</button>
20+
21+
<script src="_framework/components.server.js" autostart="false"></script>
22+
<script>
2723
// Used by InteropOnInitializationComponent
2824
function setElementValue(element, newValue) {
2925
element.value = newValue;

0 commit comments

Comments
 (0)