Prerendering a Client-side Blazor Application
Tags: blazor, aspnetcore, dotnet
Published: 2019-06-24 22:27:47

---
title: Prerendering a Client-side Blazor Application
published: true
tags: Blazor, AspNetCore, DotNet
canonical_url: https://chrissainty.com/prerendering-a-client-side-blazor-application/
---

 ![Prerendering a Client-side Blazor Application](https://chrissainty.com/content/images/2019/06/code-1076536_1920.jpg)

While prerendering is now the default for server-side Blazor applications, I only recently discovered (as in the last 48 hours) that client-side Blazor applications can take advantage of this as well. In this post, I'm going to show you how you can setup your client-side Blazor application for prerendering.

> The example project for this post can be found on [GitHub](https://github.com/chrissainty/ClientSideBlazorPrerendering).

## What is prerendering?

Prerendering is a process where all the elements of a web page are compiled on the server and static HTML is served to the client. This technique is used to help SPAs (Single Page Applications) improve their SEO (Search Engine Optimisation). Another benefit is that sites appear to load much faster.

What this means for a Blazor application is that the requested page will be built on the server and compiled to static HTML. This static HTML will include the `blazor.webassembly.js` file which is present in the standard client-side Blazor template. When the client receives this static HTML it will be processed and rendered as normal.

![Prerendering a Client-side Blazor Application](https://chrissainty.com/content/images/2019/06/blazor-client-side-prerender.jpg)

When the `blazor.webassembly.js` file is executed the mono runtime will be downloaded along with the application dlls and your application will be run. At this point all of the static prerendered elements will be replaced with interactive components and the application will become interactive.

![Prerendering a Client-side Blazor Application](https://chrissainty.com/content/images/2019/06/blazor-client-side-prerender-interactive.jpg)

Now, this may sound like a lot has to happen before your application becomes usable. But this all happens in a very short space of time and is imperceivable to most end users.

## The Prerendering Trade-off

Before we look at how to enable prerendering I want to point out that there are some trade-offs with using it.

You will no longer be able to deploy your Blazor application as static files. As we'll see in a second, prerendering requires a razor page, and that means a .NET runtime is required. While this is probably not a big issue, I do want to make sure you're aware of it.

The other trade-off is that you must manage any JavaScript calls to account for prerendering. If you attempt to perform JavaScript interop in the `OnInit` or `OnInitAsync` method of a component which is being prerendered then you will get an exception. When using prerendering all JavaScript interop calls should be moved to the `OnAfterRenderAsync` lifecycle method. This method will only be called once the page is fully rendered.

## Enabling Prerendering

We're going to start with a stand alone Blazor application and go though the steps to enable prerendering. I've created a new stand alone Blazor application using the dotnet CLI. You can also use the template in Visual Studio.

```
dotnet new blazor -o BlazorPrerendering.Client
```

If you are looking to enable prerendering on a client-side Blazor app that is already using the "Hosted" template. Then you can just add in the bits of configuration as we go along.

### Adding a Host Project

The first thing we are going to do is add a new empty ASP.NET Core Web App. Again, I'm using the dotnet CLI but you can use the templates in Visual Studio if you prefer.

```
dotnet new web -o BlazorPrerendering.Server
```

Our solution should now look like this.

![Prerendering a Client-side Blazor Application](https://chrissainty.com/content/images/2019/06/solution-structure.JPG)

Then we need to add a project reference from the server project to the client project as well as a couple of NuGet packages. We also need to add in some additional sources for loading the Blazor.Server package. So the easiest thing to do is edit the `csproj` file directly.

```
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <RestoreAdditionalProjectSources>
      https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
      https://dotnet.myget.org/F/blazor-dev/api/v3/index.json;
    </RestoreAdditionalProjectSources>
    <LangVersion>7.3</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="3.0.0-preview5-19227-01" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0-preview5-19227-01" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\BlazorPrerendering.Client\BlazorPrerendering.Client.csproj" />
  </ItemGroup>

</Project>
```

Once you're done, your project file should look like the code above.

### Configuring The Host

Now our projects are setup, we are going to make some changes to the server projects `Startup.cs`.

First, add the following code to the `ConfigureServices` method.

```
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().AddNewtonsoftJson();
    services.AddResponseCompression(opts =>
    {
        opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
            new[] { "application/octet-stream" });
    });
}
```

We'll also need to add a using statement.

```
using Microsoft.AspNetCore.ResponseCompression;
```

Then replace the code in the `Configure` method with the code below.

```
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseResponseCompression();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBlazorDebugging();
    }
    
    app.UseHttpsRedirection();

    app.UseStaticFiles();

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
        endpoints.MapFallbackToPage("/_Host");
    });

    app.UseBlazor<Client.Startup>();
}
```

We're going to add a folder called `wwwroot` to the root of the server project. Inside this folder we also need to create another called `js`.  Then inside the `js` folder we are going to create a file called `blazor.webassembly.js` and [copy in this code](https://github.com/chrissainty/ClientSideBlazorPrerendering/blob/master/src/BlazorPrerendering.Server/wwwroot/js/blazor.webassembly.js).

Once that is done we need to copy the contents of the `css` folder in the Client projects `wwwroot` folder to server projects `wwwroot` folder. Once thats all done things should look like this.

![Prerendering a Client-side Blazor Application](https://chrissainty.com/content/images/2019/06/prerendering-folder-structure.JPG)

Finally, we need to create a folder called `Pages` in the root of the server project and create a file called `_Host.cshtml` with the following code.

```
@page "/"
@namespace BlazorPrerendering.Server.Pages
@using BlazorPrerendering.Client
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Prerendering client-side Blazor</title>
    <base href="~/" />
    <environment include="Development">
        <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
              asp-fallback-href="css/bootstrap/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
              crossorigin="anonymous"
              integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" />
    </environment>
    <link href="css/site.css" rel="stylesheet" />
</head>
<body>
    <app>@(await Html.RenderStaticComponentAsync<App>())</app>

    <script src="~/js/blazor.webassembly.js"></script>
</body>
</html>
```

## Testing Prerendering

We should now be able to start up the server project and launch the application. Once the application has loaded, the easiest way to test prerendering is to disable JavaScript in your browser. Then reload the page, if the page loads then prerendering is working.

To achieve this in Chrome or Edgeium, open the dev tools and press `ctrl+shift+p` or `cmd+shift+p`, depending on your OS. The start typing javascript, you should see the option appear to disable javascript.

![Prerendering a Client-side Blazor Application](https://chrissainty.com/content/images/2019/06/chrome-dev-tools.jpg)

You should still be able to navigate around the app but you will find components will not be interactive. Go ahead and enable JavaScript again (just repeat the steps to disable but now the option will be to _Enable JavaScript_) and refresh the page, you should now have an interactive application once more.

## Summary

Prerendering is a really useful tool to have available and it's great that we can now use it with both server-side and client-side Blazor. In this post, I've shown how you can enable prerendering of your client-side Blazor applications by use of a hosted server project.