Unleashing the Power of Blazor WebAssembly with Server-Side Prerendering

Introduction

We assume you are already familiar with Blazor WebAssembly and Single Page Applications in general. Please have a look at https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor  for a quick introduction of the amazing Blazor technologie.

What is Blazor WebAssembly prerendering?

With Blazor WebAssembly prerendering, the server generates the initial HTML content of the page and sends it to the client as static HTML. This pre-rendered HTML is displayed to the user while the Blazor WebAssembly runtime is being downloaded and initialized on the client's browser. Once the runtime is ready, it takes over the static HTML, and the application becomes interactive.

What are the benefits of prerendering and why do i need it?

  1. Improved perceived performance: By providing pre-rendered HTML to the client, users can see content more quickly and have a faster initial page load experience. It enhances perceived performance and reduces the perceived latency of the application.

  2. SEO-friendly: Search engine crawlers can easily index and understand the pre-rendered HTML, which helps improve the visibility and SEO of your Blazor WebAssembly application. This can result in better search engine rankings and increased organic traffic.

  3. Enhanced user experience: Prerendering allows users to see meaningful content immediately, even before the application runtime is fully downloaded and initialized. It gives the impression that the application is loading quickly and provides a smoother transition to the interactive state.

  4. Accessibility and compatibility: Pre-rendered HTML is compatible with a wide range of browsers and devices, including those with limited JavaScript support. This ensures accessibility for users who may have JavaScript disabled or use assistive technologies to access the web.

 

 

Getting Started

 

Lets look at the setup to enable pre rendering with the well known and loved default template for Blazor Webassembly  with the feature ASP.NET Core Hosted enabled.

 

 

Very strongly summarized, we can say that pre-rendering consists in replacing the static index.html file in the wwwroot folder of the client project with a razor file in the server project. So we create a razor page in the server project called index.cshtml and copy all the content of the index.html file from the server into that razor page. After that we delete the index.html file in the client project.

 

Please follow steps 1 to 7 to create a new solution with prerendering configuration:

The Microsoft documentation for this can be found here: Prerender and integrate ASP.NET Core Razor components

 

 

It is important to note that even with server-side pre-rendering, Blazor Webassembly is still a single-page application. Therefore, all sub URLs still need to be directed to the index.cshtml. There are several ways to do this with ASP.NET Core. What we do is.:

@page "{**others}"

Please have look at the documentation Catch-all route parameters.

The double asterisk is a Catch-All parameter similar to the routing parameters for ASP.NET Core: Route templates

 

 

Lets run the application ...

You will notice three things:

  • You see the application immediately without the usual loading of the mono runtime in the browser.
  • You will notice that there is a small time window after loading, where the "Click me" button doesn't increment the counter. The reason is, that after delivering the html rendered by the server, the Blazor Webassembly runtime still needs to start so the page can continue as a single page application.
    When Blazor Webassembly is loaded, the components are rendered and the HTML is updated as needed. We will have a deeper look into this later.
  • The fetch data page works fine when you click the button in the navigation menu (the page is rendered on the client) but the application crashes when you reload the page (the page is rendered on the server).

 

Here we found the challange of switching to pre rendering especially with an already existing application. Not all components work with pre rendering out of the box. In general this applies to components with Javascript interop, navigation to another url or fetching data from the backend. This behaviour difference means that you should reload each page while testing the client. Let's take a deeper dive into the matter: Deep Dive

What about dependency injection?

When the Blazor Application is rendered in the client, than of course the dependency injection container defined in the Program.cs file of client is used. While pre rendering on the server the dependency injection container defined in the Program.cs file of the server is used. This means:

  • all required component dependencies needs to be added to the client and the server
  • Dependencies added as singleton in the client needs to be added as scoped in the server.
  • Only the dependencies of components which are actually rendered while pre rendering are required on the server. If you render a component conditionally and that condition will never be true while pre rendering, than you don't need the dependencies of this component on the server. This is very important and we will rely on that feature later
  • You can use different implementations or factories for the dependecies for client and server. We will also rely on that feature later.

 

 

A few sidenotes ...

  • The are 5 rendermods available for the component tag. One is "static". Like expected from the name, only static html is rendered. This can be used in the case you want to use razor components instead of partial views to structure your templates.

  • If you just want to customzie the index.html file by the server this approach might suit your needs. A real world usecase would be you need to support multiple tenants with each using different css files for branding.

A Deep Dive

text

Zurück

contact us

What is the sum of 8 and 5?