Inject blazor.js script tag (with all references) automatically

This commit is contained in:
Steve Sanderson 2017-12-12 00:36:09 +00:00
parent aff369e86d
commit c4fea86603
14 changed files with 121 additions and 71 deletions

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Blazor.Mono; using Microsoft.Blazor.Mono;
using Microsoft.Blazor.Server.ClientFilesystem; using Microsoft.Blazor.Server.FrameworkFiles;
using Mono.Cecil; using Mono.Cecil;
using System; using System;
using System.IO; using System.IO;

View File

@ -6,6 +6,5 @@
</head> </head>
<body> <body>
<h1>Hello</h1> <h1>Hello</h1>
<script src="/_framework/blazor.js" main="HostedInAspNet.Client.dll"></script>
</body> </body>
</html> </html>

View File

@ -22,10 +22,11 @@ namespace HostedInAspNet.Server
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
app.UseBlazorDevelopmentServer("../HostedInAspNet.Client");
} }
app.UseBlazor(clientAssemblyPath: typeof(Client.Program).Assembly.Location); app.UseBlazor(
assemblyPath: typeof(Client.Program).Assembly.Location,
staticFilesRoot: "../HostedInAspNet.Client/wwwroot");
} }
} }
} }

View File

@ -11,8 +11,10 @@ namespace MonoSanity
public void Configure(IApplicationBuilder app, IHostingEnvironment env) public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
app.UseFileServer(); app.UseFileServer(new FileServerOptions { EnableDefaultFiles = true });
app.UseBlazor(clientAssemblyPath: typeof(MonoSanityClient.Examples).Assembly.Location); app.UseBlazor(
assemblyPath: typeof(MonoSanityClient.Examples).Assembly.Location,
staticFilesRoot: null);
} }
} }
} }

View File

@ -6,7 +6,5 @@
</head> </head>
<body> <body>
<h1>Hello</h1> <h1>Hello</h1>
<script src="/_framework/blazor.js" main="StandaloneApp.dll"
references="Microsoft.Blazor.dll, netstandard.dll"></script>
</body> </body>
</html> </html>

View File

@ -133,21 +133,8 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: ()
mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']); mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']);
mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']); mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']);
// TODO: Stop hard-coding this list, and instead automatically load whatever
// dependencies were detected in ReferencedAssemblyFileProvider
const loadBclAssemblies = [
'mscorlib',
'System',
'System.Core',
'System.Console',
'System.Runtime',
];
var allAssemblyUrls = loadAssemblyUrls
.concat(loadBclAssemblies.map(name => `_framework/_bin/${name}.dll`));
Module.FS_createPath('/', 'appBinDir', true, true); Module.FS_createPath('/', 'appBinDir', true, true);
allAssemblyUrls.forEach(url => loadAssemblyUrls.forEach(url =>
FS.createPreloadedFile('appBinDir', `${getAssemblyNameFromUrl(url)}.dll`, url, true, false, null, <any>onError)); FS.createPreloadedFile('appBinDir', `${getAssemblyNameFromUrl(url)}.dll`, url, true, false, null, <any>onError));
}); });

View File

@ -20,8 +20,9 @@ namespace Microsoft.Blazor.DevHost.Server
public void Configure(IApplicationBuilder app) public void Configure(IApplicationBuilder app)
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
app.UseBlazorDevelopmentServer("."); app.UseBlazor(
app.UseBlazor(clientAssemblyPath: FindClientAssembly(app).Location); assemblyPath: FindClientAssembly(app).Location,
staticFilesRoot: "wwwroot");
} }
private static Assembly FindClientAssembly(IApplicationBuilder app) private static Assembly FindClientAssembly(IApplicationBuilder app)

View File

@ -1,11 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Blazor.Server.ClientFilesystem; using Microsoft.Blazor.Server.FrameworkFiles;
using Microsoft.Blazor.Server.WebRootFiles;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Net.Mime; using System.Net.Mime;
using System.Reflection;
namespace Microsoft.AspNetCore.Builder namespace Microsoft.AspNetCore.Builder
{ {
@ -13,12 +16,35 @@ namespace Microsoft.AspNetCore.Builder
{ {
public static void UseBlazor( public static void UseBlazor(
this IApplicationBuilder applicationBuilder, this IApplicationBuilder applicationBuilder,
string clientAssemblyPath) string assemblyPath,
string staticFilesRoot)
{ {
var frameworkFileProvider = FrameworkFileProvider.Instantiate(assemblyPath);
if (staticFilesRoot != null)
{
var env = applicationBuilder.ApplicationServices.GetRequiredService<IHostingEnvironment>();
var clientWebRoot = Path.GetFullPath(Path.Combine(env.ContentRootPath, staticFilesRoot));
var webRootFileProvider = WebRootFileProvider.Instantiate(
clientWebRoot,
Path.GetFileNameWithoutExtension(assemblyPath),
frameworkFileProvider.GetDirectoryContents("/_bin"));
applicationBuilder.UseDefaultFiles(new DefaultFilesOptions
{
FileProvider = webRootFileProvider
});
applicationBuilder.UseStaticFiles(new StaticFileOptions
{
FileProvider = webRootFileProvider
});
}
applicationBuilder.UseStaticFiles(new StaticFileOptions applicationBuilder.UseStaticFiles(new StaticFileOptions
{ {
RequestPath = "/_framework", RequestPath = "/_framework",
FileProvider = ClientFileProvider.Instantiate(clientAssemblyPath), FileProvider = frameworkFileProvider,
ContentTypeProvider = CreateContentTypeProvider(), ContentTypeProvider = CreateContentTypeProvider(),
}); });
} }

View File

@ -1,38 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System.IO;
namespace Microsoft.AspNetCore.Builder
{
public static class DevelopmentServerApplicationBuilderExtensions
{
public static void UseBlazorDevelopmentServer(
this IApplicationBuilder applicationBuilder,
string relativeSourcePath)
{
var env = applicationBuilder.ApplicationServices.GetRequiredService<IHostingEnvironment>();
var sourcePath = Path.Combine(env.ContentRootPath, relativeSourcePath);
ServeWebRoot(applicationBuilder, sourcePath);
}
private static void ServeWebRoot(IApplicationBuilder applicationBuilder, string clientAppSourceRoot)
{
var webRootFileProvider = new PhysicalFileProvider(
Path.Combine(clientAppSourceRoot, "wwwroot"));
applicationBuilder.UseDefaultFiles(new DefaultFilesOptions
{
FileProvider = webRootFileProvider
});
applicationBuilder.UseStaticFiles(new StaticFileOptions
{
FileProvider = webRootFileProvider
});
}
}
}

View File

@ -5,11 +5,10 @@ using Microsoft.Blazor.Browser;
using Microsoft.Blazor.Mono; using Microsoft.Blazor.Mono;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using System.IO; using System.IO;
using System.Reflection;
namespace Microsoft.Blazor.Server.ClientFilesystem namespace Microsoft.Blazor.Server.FrameworkFiles
{ {
internal static class ClientFileProvider internal static class FrameworkFileProvider
{ {
public static IFileProvider Instantiate(string clientAssemblyPath) public static IFileProvider Instantiate(string clientAssemblyPath)
=> new CompositeFileProvider( => new CompositeFileProvider(

View File

@ -7,7 +7,7 @@ using System.Linq;
using Mono.Cecil; using Mono.Cecil;
using Microsoft.Blazor.Internal.Common.FileProviders; using Microsoft.Blazor.Internal.Common.FileProviders;
namespace Microsoft.Blazor.Server.ClientFilesystem namespace Microsoft.Blazor.Server.FrameworkFiles
{ {
internal class ReferencedAssemblyFileProvider : InMemoryFileProvider internal class ReferencedAssemblyFileProvider : InMemoryFileProvider
{ {

View File

@ -5,7 +5,7 @@ using Microsoft.Extensions.FileProviders;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace Microsoft.Blazor.Server.ClientFilesystem namespace Microsoft.Blazor.Server.FrameworkFiles
{ {
internal class ReferencedAssemblyResolver internal class ReferencedAssemblyResolver
{ {

View File

@ -0,0 +1,58 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Blazor.Internal.Common.FileProviders;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.FileProviders;
using System.Linq;
namespace Microsoft.Blazor.Server.WebRootFiles
{
internal class IndexHtmlFileProvider : InMemoryFileProvider
{
public IndexHtmlFileProvider(string clientWebRoot, string assemblyName, IEnumerable<IFileInfo> binFiles)
: base(ComputeContents(clientWebRoot, assemblyName, binFiles))
{
}
private static IEnumerable<(string, Stream)> ComputeContents(string clientWebRoot, string assemblyName, IEnumerable<IFileInfo> binFiles)
{
var html = GetIndexHtmlContents(clientWebRoot, assemblyName, binFiles);
if (html != null)
{
var htmlBytes = Encoding.UTF8.GetBytes(html);
var htmlStream = new MemoryStream(htmlBytes);
yield return ("/index.html", htmlStream);
}
}
private static string GetIndexHtmlContents(string clientWebRoot, string assemblyName, IEnumerable<IFileInfo> binFiles)
{
var indexHtmlPath = Path.Combine(clientWebRoot, "index.html");
if (!File.Exists(indexHtmlPath))
{
return null;
}
// TODO: Consider parsing the HTML properly so for example we don't insert into
// the wrong place if there was also '</body>' in a JavaScript string literal
return File.ReadAllText(indexHtmlPath)
.Replace("</body>", CreateBootMarkup(assemblyName, binFiles) + "\n</body>");
}
private static string CreateBootMarkup(string assemblyName, IEnumerable<IFileInfo> binFiles)
{
var assemblyNameWithExtension = $"{assemblyName}.dll";
var referenceNames = binFiles
.Where(file => !string.Equals(file.Name, assemblyNameWithExtension))
.Select(file => file.Name);
var referencesAttribute = string.Join(',', referenceNames.ToArray());
return $"<script src=\"/_framework/blazor.js\"" +
$" main=\"{assemblyNameWithExtension}\"" +
$" references=\"{referencesAttribute}\"></script>";
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.FileProviders;
using System.Collections.Generic;
namespace Microsoft.Blazor.Server.WebRootFiles
{
internal static class WebRootFileProvider
{
public static IFileProvider Instantiate(
string clientWebRoot, string assemblyName, IEnumerable<IFileInfo> binFiles)
=> new CompositeFileProvider(
new IndexHtmlFileProvider(clientWebRoot, assemblyName, binFiles),
new PhysicalFileProvider(clientWebRoot));
}
}