'What is the right way to prerender Blazor WebAssembly?

It almost works after the following steps:

  1. Install the hosted version of blazorwasm template app.
    dotnet new blazorwasm --hosted -o HostedWasm
    
  2. Copy _Hosted.cshtml from blazorserver template to the Pages folder.
  3. Change endpoints.MapFallbackToFile("index.html") to endpoints.MapFallbackToPage("/_Host") in Startup.cs of the server
  4. Change <script src="_framework/blazor.server.js"></script> to <script src="_framework/blazor.webassembly.js"></script> in _Host.cshtml

Now if you dotnet run the server you will be able to navigate template pages with prerendered HTML.

But, I have two questions:

  1. Is it the "right" way to do the prerendering of Blazor WebAssembly? I see nothing about this in the docs.
  2. How to share DI between server-side and client-side? Now, if you navigate / and then going to /fetchdata everything will be fine, but if you then use F5 (e.g refresh) on /fetchdata path, you will see

InvalidOperationException: Cannot provide a value for property 'Http' on type 'HostedWasm.Client.Pages.FetchData'. There is no registered service of type 'System.Net.Http.HttpClient'.

To fix it you need to copy HttpClient configuration code from Client/Program.cs to Server/Startup.cs



Solution 1:[1]

Andrew Lock's excellent blog post, Enabling prerendering for Blazor WebAssembly apps, gives the best instructions, IMO. To repeat his steps here:

  1. Add _Host Page, dotnet new page -o Pages -n _Host --no-pagemodel
  2. Copy Client/wwwroot/index.html into it, keeping @page at the top
  3. Add tag helper, @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
  4. Replace <div id="app"> with <component type="typeof(BlazorApp1.App)" render-mode="WebAssemblyPrerendered" />
  5. Remove builder.RootComponents.Add<App>("#app") from Program.cs
  6. Add an http client to the server, e.g. services.AddSingleton<HttpClient>.

He goes on to link to other blog posts which debate the 'right' to handle the missing HttpClient problem. I think just injecting a client is the 'right' approach. It's a simple solution. The app is only running on the server for a few seconds. The pre-rendered app isn't interactive anyway, so it's not like the user is going to click around a bunch.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 James Coliz