Aspnetcore: Isolated Blazor server prerendering

Created on 14 Jun 2020  Â·  9Comments  Â·  Source: dotnet/aspnetcore

I use client side Blazor WebAssembly and when I open a page for the first time I see "Loading..." during several seconds. I decided to enable server side pre-rendering to show some static content for users and search engines.

I added the following line to _Host.cshtml
<app>@(await Html.RenderComponentAsync<ClientSide.App>(RenderMode.Static))</app>

but I have the problem, there are a lot of services that were developed on client and server side that can be used only on these sides respectively. As far as I understand if I want to use server pre-rendering, server side service collection will contain client side services as well, that's leading to conflict and confusion for me.

How can I deal with that? Is there way to render entire client side beginning with WebAssemblyHostBuilder.CreateDefault() in Program.cs separately instead of rendering only ClientSide.App component in _Host.cshtml? Or is there way to separate client side servicecollection from server side servicecollection at least? What do you think? Thanks!

Answered Resolved area-blazor question

Most helpful comment

How can I deal with that? Is there way to render entire client side beginning with WebAssemblyHostBuilder.CreateDefault() in Program.cs separately instead of rendering only ClientSide.App component in _Host.cshtml? Or is there way to separate client side servicecollection from server side servicecollection at least? What do you think? Thanks!

You do this manually:

  • Extract common services that you want to use serverside during prerendering into a separate method.
  • Replace clientside services that don't make sense on a prerendering context with serverside implementations.
  • Avoid rendering paths that make use of services that don't have a server replacement.

Prerendering client-side apps is not transparent and it is unlikely it will ever be. Properly factoring your app to support it is the best way to approach the problem.

All 9 comments

My general approach is to detect the routes that use callbacks (e.g. auth, Paypal, whatever it might be) and not have those server side rendered so not to interfere.

For most of the other routes I generally still need to configure the same dependencies, albeit they may have different scopes. On occasion where there is a component that should not render server side, I add a condition around that specific component with the dependency, or register a no-op service...it depends on the situation.

I don't know if this helps but I made a post for client app running an app with server side rendering.
Server Side Render Blazor Client Side App (WASM)

I also wrote a post on how to detect if you are running on the server or the client:
Blazor — How to pick and choose what you render on the server

Specifically in the case of the route:

<app>
    @if (HttpContext.Request.Path.StartsWithSegments("/authentication"))
    {
        <text>Loading...</text>
    }
    else
    {
        <component type="typeof(App)" render-mode="Static"/>
    }
</app>

srpeirce thanks, but it seems you didn't get my question completely..

@DenisKudelin I've re-read.

have the problem, there are a lot of services that were developed on client and server side that can be used only on these sides respectively. As far as I understand if I want to use server pre-rendering, server side service collection will contain client side services as well, that's leading to conflict and confusion for me.

I don't quite understand...you mean registering services in the Server project (Startup.cs) is conflicting with those registered in the Client project (Program.cs)?

That shouldn't be the case, you need to register the dependencies in each of those places - if you register a service in the Server it will not be automatically registered in the Client, and vice-versa.

If I have mis-understood please re-ask, or please provide a concrete example.

@DenisKudelin I've re-read.

have the problem, there are a lot of services that were developed on client and server side that can be used only on these sides respectively. As far as I understand if I want to use server pre-rendering, server side service collection will contain client side services as well, that's leading to conflict and confusion for me.

I don't quite understand...you mean registering services in the Server project (Startup.cs) is conflicting with those registered in the Client project (Program.cs)?

That shouldn't be the case, you need to register the dependencies in each of those places - if you register a service in the Server it will not be automatically registered in the Client, and vice-versa.

If I have mis-understood please re-ask, or please provide a concrete example.

Yes, you understand correctly. But in order to prerender client side, currently I need to combine services from both sides, because the serviceprovider is common for server and for client in this case.

Aha okay, so yes, you will need to register the mutual dependencies on both client and server as they are separate applications.

Does this make sense? Was there any follow up question?

Aha okay, so yes, you will need to register the mutual dependencies on both client and server as they are separate applications.

Does this make sense? Was there any follow up question?

How to avoid that? My services are conflicting and confusing each other, client services are not compatible with server and vise versa. Perfectly, I want to completely separate them and run client side rendering since WebAssemblyHostBuilder.CreateDefault. But splitting serviceproviders will be okay too.

Please can you provide a bare-bone example project of Github to give a concrete example of your problem?

How can I deal with that? Is there way to render entire client side beginning with WebAssemblyHostBuilder.CreateDefault() in Program.cs separately instead of rendering only ClientSide.App component in _Host.cshtml? Or is there way to separate client side servicecollection from server side servicecollection at least? What do you think? Thanks!

You do this manually:

  • Extract common services that you want to use serverside during prerendering into a separate method.
  • Replace clientside services that don't make sense on a prerendering context with serverside implementations.
  • Avoid rendering paths that make use of services that don't have a server replacement.

Prerendering client-side apps is not transparent and it is unlikely it will ever be. Properly factoring your app to support it is the best way to approach the problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BrennanConroy picture BrennanConroy  Â·  3Comments

ipinak picture ipinak  Â·  3Comments

Kevenvz picture Kevenvz  Â·  3Comments

UweKeim picture UweKeim  Â·  3Comments

rbanks54 picture rbanks54  Â·  3Comments