BlazorWasmPreRendering.Build
2.0.0-preview.4
See the version list below for details.
dotnet add package BlazorWasmPreRendering.Build --version 2.0.0-preview.4
NuGet\Install-Package BlazorWasmPreRendering.Build -Version 2.0.0-preview.4
<PackageReference Include="BlazorWasmPreRendering.Build" Version="2.0.0-preview.4" />
paket add BlazorWasmPreRendering.Build --version 2.0.0-preview.4
#r "nuget: BlazorWasmPreRendering.Build, 2.0.0-preview.4"
// Install BlazorWasmPreRendering.Build as a Cake Addin #addin nuget:?package=BlazorWasmPreRendering.Build&version=2.0.0-preview.4&prerelease // Install BlazorWasmPreRendering.Build as a Cake Tool #tool nuget:?package=BlazorWasmPreRendering.Build&version=2.0.0-preview.4&prerelease
BlazorWasmPreRendering.Build
📝Summary
When you publish your Blazor WebAssembly app, this package pre-renders and saves the app as static HTML files in your public folder.
This will help make the contents of your Blazor WebAssembly static apps findable in internet search and be visible from the OGP client.
An output of "dotnet publish" before installing this package:
And after installing this package:
🚀Quick Start
Install this package to your Blazor WebAssembly project.
dotnet add package BlazorWasmPreRendering.Build --prerelease
Basically, that's all.
Once installing this package is done, the output of the dotnet publish
command will include pre-rendered contents! 🎉
⚙️Configurations
Services registration
If you are registering any services (except HttpClient that isn't specially configured) to the service provider at the startup of your Blazor WebAssembly app, please extract that process to the static method named static void ConfigureServices(IServiceCollection services, string baseAddress)
.
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
// 👇 Extract service registration...
services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) });
services.AddScoped<IFoo, MyFoo>();
await builder.Build().RunAsync();
}
}
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
ConfigureServices(builder.Services, builder.HostEnvironment.BaseAddress);
await builder.Build().RunAsync();
}
// 👇 ... to this named static method.
private static void ConfigureServices(IServiceCollection services, string baseAddress)
{
services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) });
services.AddScoped<IFoo, MyFoo>();
}
}
And, if you implement the entry point as C# 9 top-level statement style, then you have to also extract the service-registration process to the static local function named static void ConfigureServices(IServiceCollection services, string baseAddress)
.
NOTICE: The "ConfigureServices" local function must be "static" local function.
// The "Program.cs" that is C# 9 top-level statement style entry point.
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
ConfigureServices(builder.Services, builder.HostEnvironment.BaseAddress);
await builder.Build().RunAsync();
// 👇 extract the service-registration process to the static local function.
static void ConfigureServices(IServiceCollection services, string baseAddress)
{
services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) });
services.AddScoped<IFoo, MyFoo>();
}
Aside: C# 9 top-level statement style entry point can be used for only .NET6 or above.
This package calls the ConfigureServices()
static method (or static local function) inside of your Blazor WebAssembly app when pre-renders it if that method exists.
This is important to your Blazor WebAssembly components work fine in the pre-rendering process.
Note: other arguments of ConfigureServices() method
The ConfigureServices()
method can also have an IConfiguration
argument reflected with the contents of the wwwroot/appsetting.json
JSON file.
Root component type and selector
In some cases, suppose the type and selector of the root component of your Blazor WebAssembly app are not {RootNamespace}.App
and #app
or app
.
In that case, you have to describe that information explicitly in the project file (.csproj) of your Blazor WebAssembly app, like this.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingRootComponentType>My.Custom.RootComponentClass</BlazorWasmPrerenderingRootComponentType>
<BlazorWasmPrerenderingRootComponentSelector>.selector-for-root</BlazorWasmPrerenderingRootComponentSelector>
</PropertyGroup>
...
If the root component doesn't live in the application assembly, you can specify assembly name in the <BlazorWasmPrerenderingRootComponentType>
peoperty value, like this.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingRootComponentType>My.Custom.RootComponentClass, My.CustomAssembly</BlazorWasmPrerenderingRootComponentType>
...
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
Note: If the specified type was not found...
If the specified type was not found, as a fallback behavior, this package tries to find the root component type (which has the type name "App" and inherits ComponentBase
type) from all assemblies that referenced from the application assembly.
Hosting Environment
The host environment returns the environment name "Prerendering" during the pre-rendering process.
@inject IWebAssemblyHostEnvironment HostEnv
<p>@HostEnv.Environment</p>
If you want to customize the host environment name during the pre-rendering process, please specify the "BlazorWasmPrerenderingEnvironment" MSBuild property inside your .csproj file or inside of the "dotnet publish" command-line argument.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingEnvironment>Production</BlazorWasmPrerenderingEnvironment>
...
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
Output style
By default, all staticalized output HTML files are named "index.html" and are placed in subfolders in the same hierarchy as a request URL path.
But if you set the BlazorWasmPrerenderingOutputStyle
MSBuild property to AppendHtmlExtension
when you publish the project, the staticalized files are named with each request URL path appended ".html" file extension.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingOutputStyle>AppendHtmlExtension</BlazorWasmPrerenderingOutputStyle>
...
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
Delete the "Loading..." contents
By default, this package keeps the "Loading..." contents in the original fallback page (such as an index.html
) into prerendered output static HTML files.
And, prerendered contents are invisible on the browser screen.
(Only search engine crawlers can read them.)
That is by design because even if users can see the prerendered contents immediately after initial page loading, that page can not interact with users for a few seconds until the Blazor WebAssembly runtime has been warmed up.
However, in some cases, developers can control the user interactions completely until the Blazor WebAssembly runtime warmed up, and they would like to make the prerendered contents are visible immediately.
For that case, set the BlazorWasmPrerenderingDeleteLoadingContents
MSBuild property to true
.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingDeleteLoadingContents>true</BlazorWasmPrerenderingDeleteLoadingContents>
...
When that MSBuild property is set to true
, this package deletes the "Loading..." contents from prerendered static HTML files and does not hide prerendered contents from users.
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
Url path to explicit fetch
By default, this package follows all of <a>
links recursively inside the contents starting from the root index (/
) page to save them statically.
However, in some cases, there are pages that are not linked from anywhere, such as an "Easter Egg" page.
To support that case, please set the URL path list that you want to fetch explicitly to the BlazorWasmPrerenderingUrlPathToExplicitFetch
MSBuild property as a semicolon-separated string.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingUrlPathToExplicitFetch>/unkinked/page1;/unlinked/page2</BlazorWasmPrerenderingUrlPathToExplicitFetch>
...
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
Render mode
As you may know, this package is based on the standard ASP.NET Core Blazor server-side prerendering support.
By default, the render mode of prerendering is Static
.
And, you can specify the render mode to WebAssemblyPrerendered
via the BlazorWasmPrerenderingMode
MSBuild property if you want.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingMode>WebAssemblyPrerendered</BlazorWasmPrerenderingMode>
...
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
As the side effect of using the WebAssemblyPrerendered
render mode, even you specify any values to the "BlazorWasmPrerenderingDeleteLoadingContents" MSBuild property, the "Loading..." contents are always removed, and prerendered contents never are invisible.
When you use the WebAssemblyPrerendered
render mode, please pay attention to implementing a startup code of the Blazor WebAssembly app.
Usually, a startup code of the Blazor WebAssembly app should be like this.
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.RootComponents.Add<HeadOutlet>("head::after");
However, if you use the WebAssemblyPrerendered
render mode when prerendering, you should change the startup code below.
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// 👇 Add the condition that determine root components are
// already registered via prerednered HTML contents.
if (!builder.RootComponents.Any())
{
builder.RootComponents.Add<App>("app");
builder.RootComponents.Add<HeadOutlet>("head::after");
}
That is because the root component types and their insertion positions are specified inside of the prerendered HTML contents, not inside of your C# code when the render mode is WebAssemblyPrerendered
.
Moreover, on .NET 6, you can also use the "persisting prerendered state" feature.
When the render mode is WebAssemblyPrerendered
, this package injects the <persist-component-state />
tag helper into the fallback page.
So what you should do is inject the PersistentComponentState
service into your component and use it to store the component state at prerendering and retrieve the saved component state at the Blazor WebAssembly is started.
Using the WebAssemblyPrerendered
render mode and the persisting component state feature has the significant potential to far improve the perceived launch speed of Blazor WebAssembly apps.
For more details, please see also the following link.
- "Persist prerendered state - Prerender and integrate ASP.NET Core Razor components | Microsoft Docs".
Locale
The pre-rendering process will default be taken under the "en" culture. If you want to pre-render that with another culture, you can do that by specifying the BlazorWasmPrerenderingLocale
MSBuild property.
You can set a comma-separated locale list such as "en", "ja-JP,en-US", etc. those used when crawling, to the BlazorWasmPrerenderingLocale
MSBuild property.
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
...
<PropertyGroup>
<BlazorWasmPrerenderingLocale>ja-JP,en-US</BlazorWasmPrerenderingLocale>
...
🛠️Troubleshooting
If any exceptions happen in the prerendering process, the exception messages and stack traces will be shown in the console output of the dotnet publish
command.
Those outputs should be helpful for you to investigate and resolve those exceptions.
But in some cases, developers may want to investigate the living prerendering process.
To do that, please set the BlazorWasmPrerenderingKeepServer
MSBuild property to true
.
dotnet publish -c:Release -p:BlazorWasmPrerenderingKeepServer=true
(* See also: MSBuild properties reference for the "BlazorWasmPreRendering.Build")
When that MSBuild property is set to true
, the dotnet publish
command will not be exited, and the prerendering process is kept running until the Ctrl + C keyboard combination is pressed.
During the prerendering process is running, developers can investigate it.
🔗Appendix
- If you would like to change a title or any meta elements for each page in your Blazor WebAssembly app, I recommend using the "Blazor Head Element Helper" NuGet package.
- Since the ver.1.0.0 preview 8 of this package, the .NET 6
<PageTitle>
and<HeadContent>
components are also statically pre-rendered properly.
- Since the ver.1.0.0 preview 8 of this package, the .NET 6
- If you would like to deploy your Blazor WebAssembly app to GitHub Pages, I recommend using the "Publish SPA for GitHub Pages" NuGet package.
- The "Awesome Blazor Browser" site is one of a good showcase of this package. That site is republishing every day by GitHub Actions with pre-rendering powered by this package.
⚠️Notice
This package is now experimental stage.
We can expect this package will work fine with a simple Blazor WebAssembly project.
But I'm not sure this package works fine even with a complicated real-world Blazor WebAssembly project at this time.
I welcome to fork and improve this project on your hand.
🎉Release notes
📢License
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (7)
Showing the top 5 popular GitHub repositories that depend on BlazorWasmPreRendering.Build:
Repository | Stars |
---|---|
ant-design-blazor/ant-design-blazor
🌈A rich set of enterprise-class UI components based on Ant Design and Blazor.
|
|
jsakamoto/BlazorWasmPreRendering.Build
When you publish your Blazor Wasm app, this package pre-renders and saves the app as static HTML files in your public folder.
|
|
jsakamoto/awesome-blazor-browser
A Blazor WebAssembly app for browsing the "Awesome Blazor" resources.
|
|
jsakamoto/Toolbelt.Blazor.HeadElement
Head element support (change the document title, "meta" elements such as OGP, and "link" elements) for Blazor apps.
|
|
CropperBlazor/Cropper.Blazor
Cropper.js as Blazor component for cropping images
|
Version | Downloads | Last updated |
---|---|---|
5.0.0 | 443 | 11/12/2024 |
5.0.0-preview.2 | 654 | 9/23/2024 |
5.0.0-preview.1 | 409 | 4/18/2024 |
4.0.1 | 744 | 9/23/2024 |
4.0.0 | 3,246 | 4/18/2024 |
3.1.0-preview.4 | 4,304 | 9/20/2023 |
3.1.0-preview.3 | 169 | 9/14/2023 |
3.1.0-preview.2 | 114 | 9/3/2023 |
3.1.0-preview.1 | 171 | 9/2/2023 |
3.0.0-preview.2 | 404 | 8/3/2023 |
3.0.0-preview.1 | 222 | 7/9/2023 |
2.0.0-preview.9 | 960 | 5/28/2023 |
2.0.0-preview.8 | 1,036 | 3/15/2023 |
2.0.0-preview.7 | 1,045 | 11/22/2022 |
2.0.0-preview.6 | 117 | 11/20/2022 |
2.0.0-preview.5 | 233 | 11/16/2022 |
2.0.0-preview.4 | 617 | 11/3/2022 |
2.0.0-preview.3.1 | 110 | 11/3/2022 |
2.0.0-preview.2 | 135 | 10/23/2022 |
2.0.0-preview.1 | 163 | 10/22/2022 |
1.0.0-preview.28.0 | 707 | 9/22/2022 |
1.0.0-preview.27.0 | 114 | 9/21/2022 |
1.0.0-preview.26.0 | 889 | 7/23/2022 |
1.0.0-preview.25.1 | 123 | 7/23/2022 |
1.0.0-preview.25.0 | 226 | 7/10/2022 |
1.0.0-preview.24.1 | 368 | 6/28/2022 |
1.0.0-preview.24.0 | 1,138 | 4/19/2022 |
1.0.0-preview.23.0 | 190 | 3/16/2022 |
1.0.0-preview.22.0 | 184 | 3/10/2022 |
1.0.0-preview.21.0 | 138 | 3/9/2022 |
1.0.0-preview.20.0 | 123 | 3/9/2022 |
1.0.0-preview.19.0 | 141 | 2/26/2022 |
1.0.0-preview.18.0 | 131 | 2/26/2022 |
1.0.0-preview.17.0 | 1,613 | 2/23/2022 |
1.0.0-preview.16.0 | 150 | 2/18/2022 |
1.0.0-preview.15.0 | 127 | 2/15/2022 |
1.0.0-preview.14.0 | 142 | 1/18/2022 |
1.0.0-preview.13.0 | 214 | 12/18/2021 |
1.0.0-preview.12.0 | 282 | 12/18/2021 |
1.0.0-preview.11.4 | 194 | 12/16/2021 |
1.0.0-preview.10.1 | 271 | 12/11/2021 |
1.0.0-preview.9.0 | 513 | 10/16/2021 |
1.0.0-preview.8.0 | 235 | 9/19/2021 |
1.0.0-preview.7.1 | 296 | 8/24/2021 |
1.0.0-preview.6 | 161 | 7/27/2021 |
1.0.0-preview.5 | 258 | 7/23/2021 |
1.0.0-preview.4.1 | 338 | 5/22/2021 |
1.0.0-preview.4 | 237 | 5/9/2021 |
1.0.0-preview.3 | 193 | 5/9/2021 |
1.0.0-preview.2 | 204 | 5/9/2021 |
v.2.0.0-preview.4
- Improve: Add support for the "Blazor Wasm Antivirus Protection".
To see all the change logs, please visit the following URL.
- https://github.com/jsakamoto/BlazorWasmPreRendering.Build/blob/master/RELEASE-NOTES.txt