Skip to content

Make Razor Components apps not use Blazor build #6562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

SteveSandersonMS
Copy link
Member

@SteveSandersonMS SteveSandersonMS commented Jan 10, 2019

Previously for Razor Components, we ran the entire Blazor build process which includes:

  • Enabling the components Razor compiler
  • Putting the .NET assemblies in a client-downloadable location (including linking them by default)
  • Tracing the dependency graph and generating a boot.json file
  • Writing a blazor.config.json file to the server project's bin dir to specify the client app location
  • Copying any library-embedded resources into bin/dist
  • Copying the Mono WebAssembly binaries into bin/dist
  • A similar set of complex modifications to the publishing process (e.g., copying the client app dist files into the server project's bin dir)

The considerable majority of this is irrelevant for Razor Components apps, and is somewhat harmful because it not only makes the build slower and have more potential failure points, but also has runtime drawbacks such as #5589. Once #6538 is merged, we have a way to include only the "enable the components Razor compiler" part of the above and none of the rest.

This PR builds on #6538, eliminating the remaining runtime dependencies on Blazor build artifacts:

  • We no longer require the blazor.config.json file, because we no longer try to load any static assets from the client app location (we serve static content directly from the server project)
  • We no longer need to load blazor.server.js from the client app project, because it's now served directly from an embedded resource in .Components.Server middleware
  • We no longer require there to be a boot.json

This PR also cleans up some naming, such as renaming UseServerSideBlazor to UseRazorComponents, renaming blazor.server.js to components.server.js, and a few others.

The net result is that the Razor Components template can be extremely simple. Plus its build process is trivial, and we don't need any custom publishing steps. And there's no further technical requirement for it to be two separate projects - one would work just the same.

Caveat: This PR also has the side-effect that the Razor Components template will no longer support library-embedded resources or auto-rebuild by default, because the implementations for those are in the Blazor-specific packages. We can add these features back soon. This is tracked in #6442.

</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputType>Library</OutputType>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point. It was needed only because the SDK was set to Microsoft.NET.Sdk.Web, which it shouldn't have been. I've changed the SDK to Microsoft.NET.Sdk.Razor and now we no longer need to override OutputType.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😻

// Use component registrations and static files from the client startup.
app.UseServerSideBlazor<App.Startup>();
app.UseStaticFiles();
app.UseRazorComponents<App.Startup>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

/// <param name="builder">The <see cref="IApplicationBuilder"/>.</param>
/// <typeparam name="TStartup">A components app startup type.</typeparam>
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseRazorComponents<TStartup>(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically we don't need the TStartup at all. I've left it here for symmetry with AddRazorComponents and in case we want to reserve the right to use that info in the future.

I'm totally open to changing this though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know. I think we should leave it as-is until we resolve all of the dependencies and tweaks needed to ship preview2.

// add SignalR and BlazorHub automatically.
if (options.UseSignalRWithBlazorHub)
{
builder.UseSignalR(route => route.MapHub<BlazorHub>(BlazorHub.DefaultPath));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be renamed to components?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, eventually. There are lots of remaining bits of renaming-cleanup like that, but I'm not trying to get all of them done before Preview 2. I'm only focused on the ones that are really in developers' faces in default scenarios, which this isn't.

builder.UseSpa(spa => { });

return builder;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This got me thinking.
If we somehow change the way we distribute /_framework files

The core of this method would be
builder.UseSignalR();
builder.UseSpa();

I'm wondering what your thoughts are on having something like this directly on the template.

builder.UseSignalR(r => r.MapComponentsHub());
builder.UseSpa(spa =>{ });

compared to
app.UseRazorComponents()

The reason for it being that it's more straightforward what's going on in the pipeline and its easier to manipulate, for example to add Azure SignalR (it composes better).

Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we somehow change the way we distribute /_framework files

Yep, we would need to do that. I'd be keen not to have components.server.js as a physical file in the project, because that gets into difficulty with versioning mismatches and people being confused into thinking it's a good idea to edit the contents or trying to bundle it with their own files.

The mechanism here of serving it from middleware in UseRazorComponents is preferable I think, but we can review the factoring as we go on. I'm totally open to making UseRazorComponents just be shorthand for a collection of lower-level middlewares you can add manually if you prefer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

. I'd be keen not to have components.server.js as a physical file in the project,

Also servicing.

@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/make-razor-components-apps-not-require-blazor-build branch from aeef043 to 910d63c Compare January 10, 2019 11:45
@SteveSandersonMS SteveSandersonMS changed the base branch from stevesa/rename-components-build-to-blazor-build to master January 10, 2019 11:45

namespace Microsoft.AspNetCore.Builder
{
internal class FrameworkFilesProvider : IFileProvider
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simpler way to do this would be to just use the embedded file provider no? If this is a temporary workaround for some stuff, I'm fine with it for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. I've updated the code to remove FrameworkFilesProvider and use EmbeddedFileProvider.

Previously I was trying to unify how the components.server.js file and the blazor.boot.json file were served. But since blazor.boot.json is temporary it doesn't make sense to orient the design around that.

If this is a temporary workaround for some stuff

Serving a stub file for blazor.boot.json is a temporary workaround, but serving components.server.js from an embedded resource will hopefully remain.

@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/make-razor-components-apps-not-require-blazor-build branch from 910d63c to 9b650ac Compare January 11, 2019 10:56
{
builder.UseStaticFiles(new StaticFileOptions
{
FileProvider = new EmbeddedFileProvider(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend using the ManifestEmbeddedFileProvider instead.
This one has some limitations and is more hacky than the ManifestEmbeddedFileProvider we use in the identity UI and other libraries, so it would be better if we just use the same all over the place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants