Support loading embedded resources for server-side execution too

This commit is contained in:
Steve Sanderson 2018-07-16 13:57:01 +01:00
parent 9778b2054a
commit 970f591803
3 changed files with 53 additions and 40 deletions

View File

@ -6,10 +6,16 @@ import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack';
import { OutOfProcessRenderBatch } from './Rendering/RenderBatch/OutOfProcessRenderBatch';
import { internalFunctions as uriHelperFunctions } from './Services/UriHelper';
import { renderBatch } from './Rendering/Renderer';
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
let connection : signalR.HubConnection;
function boot() {
// In the background, start loading the boot config and any embedded resources
const embeddedResourcesPromise = fetchBootConfigAsync().then(bootConfig => {
return loadEmbeddedResourcesAsync(bootConfig);
});
connection = new signalR.HubConnectionBuilder()
.withUrl('/_blazor')
.withHubProtocol(new MessagePackHubProtocol())
@ -24,13 +30,16 @@ function boot() {
connection.on('JS.Error', unhandledError);
connection.start()
.then(() => {
.then(async () => {
DotNet.attachDispatcher({
beginInvokeDotNetFromJS: (callId, assemblyName, methodIdentifier, argsJson) => {
connection.send('BeginInvokeDotNetFromJS', callId ? callId.toString() : null, assemblyName, methodIdentifier, argsJson);
}
});
// Ensure any embedded resources have been loaded before starting the app
await embeddedResourcesPromise;
connection.send(
'StartCircuit',
uriHelperFunctions.getLocationHref(),

View File

@ -7,6 +7,7 @@ import { renderBatch } from './Rendering/Renderer';
import { RenderBatch } from './Rendering/RenderBatch/RenderBatch';
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
import { Pointer } from './Platform/Platform';
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
async function boot() {
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
@ -16,11 +17,8 @@ async function boot() {
};
// Fetch the boot JSON file
// Later we might make the location of this configurable (e.g., as an attribute on the <script>
// element that's importing this file), but currently there isn't a use case for that.
const bootConfigResponse = await fetch('_framework/blazor.boot.json');
const bootConfig: BootJsonData = await bootConfigResponse.json();
const embeddedResourcePromises = startLoadingEmbeddedResources(bootConfig);
const bootConfig = await fetchBootConfigAsync();
const embeddedResourcesPromise = loadEmbeddedResourcesAsync(bootConfig);
if (!bootConfig.linkerEnabled) {
console.info('Blazor is running in dev mode without IL stripping. To make the bundle size significantly smaller, publish the application or see https://go.microsoft.com/fwlink/?linkid=870414');
@ -38,44 +36,11 @@ async function boot() {
}
// Before we start running .NET code, be sure embedded content resources are all loaded
await Promise.all(embeddedResourcePromises)
await embeddedResourcesPromise;
// Start up the application
const mainAssemblyName = getAssemblyNameFromUrl(bootConfig.main);
platform.callEntryPoint(mainAssemblyName, bootConfig.entryPoint, []);
}
function startLoadingEmbeddedResources(bootConfig: BootJsonData) {
const cssLoadingPromises = bootConfig.cssReferences.map(cssReference => {
const linkElement = document.createElement('link');
linkElement.rel = 'stylesheet';
linkElement.href = cssReference;
return loadResourceFromElement(linkElement);
});
const jsLoadingPromises = bootConfig.jsReferences.map(jsReference => {
const scriptElement = document.createElement('script');
scriptElement.src = jsReference;
return loadResourceFromElement(scriptElement);
});
return cssLoadingPromises.concat(jsLoadingPromises);
}
function loadResourceFromElement(element: HTMLElement) {
return new Promise((resolve, reject) => {
element.onload = resolve;
element.onerror = reject;
document.head.appendChild(element);
});
}
// Keep in sync with BootJsonData in Microsoft.AspNetCore.Blazor.Build
interface BootJsonData {
main: string;
entryPoint: string;
assemblyReferences: string[];
cssReferences: string[];
jsReferences: string[];
linkerEnabled: boolean;
}
boot();

View File

@ -0,0 +1,39 @@
export async function fetchBootConfigAsync() {
// Later we might make the location of this configurable (e.g., as an attribute on the <script>
// element that's importing this file), but currently there isn't a use case for that.
const bootConfigResponse = await fetch('_framework/blazor.boot.json');
return bootConfigResponse.json() as Promise<BootJsonData>;
}
export function loadEmbeddedResourcesAsync(bootConfig: BootJsonData): Promise<any> {
const cssLoadingPromises = bootConfig.cssReferences.map(cssReference => {
const linkElement = document.createElement('link');
linkElement.rel = 'stylesheet';
linkElement.href = cssReference;
return loadResourceFromElement(linkElement);
});
const jsLoadingPromises = bootConfig.jsReferences.map(jsReference => {
const scriptElement = document.createElement('script');
scriptElement.src = jsReference;
return loadResourceFromElement(scriptElement);
});
return Promise.all(cssLoadingPromises.concat(jsLoadingPromises));
}
function loadResourceFromElement(element: HTMLElement) {
return new Promise((resolve, reject) => {
element.onload = resolve;
element.onerror = reject;
document.head.appendChild(element);
});
}
// Keep in sync with BootJsonData in Microsoft.AspNetCore.Blazor.Build
interface BootJsonData {
main: string;
entryPoint: string;
assemblyReferences: string[];
cssReferences: string[];
jsReferences: string[];
linkerEnabled: boolean;
}