BlazorWasmPreRendering.Build

repository·master·Indexed 43 days ago

https://github.com/jsakamoto/blazorwasmprerendering.build

A build-time tool for Blazor WebAssembly applications that automates pre-rendering during the dotnet publish process. It generates static HTML files to improve SEO and Open Graph Protocol (OGP) visibility. The package supports customizable root components, hosting environment names, and output styles, and offers a WebAssemblyPrerendered mode for state persistence and improved launch speed.

Tokens
6.5K
Snippets
25
Records
31
Agent score
55%

What's inside BlazorWasmPreRendering.Build

  1. Overview of BlazorWasmPreRendering.Build

    master
    BlazorWasmPreRendering.Build is a build-time tool for Blazor WebAssembly applications. When you run dotnet publish, this package pre-renders your application and saves the output as static HTML files into your public folder. This process makes your Blazor WebAssembly app's content discoverable by search engines (SEO) and visible to Open Graph Protocol (OGP) clients.
  2. Compare BlazorWasmApp sample projects

    master

    The repository includes three sample applications demonstrating different configurations of Blazor WebAssembly with pre-rendering. Use these as templates depending on your framework version and project structure requirements:

    • BlazorWasmApp0: Best for .NET 10.0 projects using a Client + Razor Class Library (RCLIb) structure. It supports PWA, Brotli Loader, AngleSharp, Localization, and Lazy Loading assemblies. It uses the <app> root element and <PageTitle> for titles.
    • BlazorWasmApp1: Best for .NET 9.0 projects with a standard Client structure. It supports GitHub Pages deployment and Lazy Loading assemblies. It uses <div id='app'> as the root element and <Title> for titles.
    • BlazorWasmApp2: Best for .NET 8.0 projects using a Component + Client architecture. It uses the <app> root element.
    |                   |BlazorWasmApp0| BlazorWasmApp1   | BlazorWasmApp2
    |-------------------|--------------|------------------|--------------
    |Framework          | .NET 10.0     | .NET 9.0        | .NET 8.0
    |Projects           | Client + RCLIb| Client           | Component + Client   
    |Root element       | `<app>`      | `<div id='\\'app\\'>` | `<app>`
    |Used in E2E test   | ✅ Yes       | ✅ Yes          | ✅ Yes
    |Page title        | `<PageTitle>`| `<Title>`        | -
    |PWA                | ✅ Yes       | -               | -
    |Deploy to GitHub Pages| -         | ✅ Yes          | -
    |Brotli Loader      | ✅ Yes       | -               | -
    |Has AngleSharp dependency| ✅Yes  | -               | -
    |Localization       | ✅ Yes       | -               | -
    |Lazy Load Assembly | ✅ Yes       | ✅ Yes          | -
  3. Use WebAssemblyPrerendered mode and persist state

    master

    The default render mode is Static. You can switch to WebAssemblyPrerendered via the BlazorWasmPrerenderingMode MSBuild property.

    Key implications of WebAssemblyPrerendered mode:

    1. Loading Overlay: The loading overlay is automatically disabled and "Loading..." contents are removed.
    2. Startup Code: You must check if root components are already registered to avoid errors when the runtime starts:
      if (!builder.RootComponents.Any()) 
      {
          builder.RootComponents.Add<App>("#app");
          builder.RootComponents.Add<HeadOutlet>("head::after");
      }
    3. State Persistence: This mode injects the <persist-component-state /> tag helper. You should use PersistentComponentState to store state during pre-rendering and retrieve it when the WebAssembly app starts to improve perceived launch speed.
    <PropertyGroup>
      <BlazorWasmPrerenderingMode>WebAssemblyPrerendered</BlazorWasmPrerenderingMode>
    </PropertyGroup>
  4. Configure MSBuild properties via dotnet publish command line

    master

    You can pass MSBuild properties during the dotnet publish execution using the -p:{name}={value} syntax.

    Important: If a property value contains a comma (e.g., for BlazorWasmPrerenderingLocale), you must replace the comma with %2c to ensure the command line parses it correctly.

    dotnet publish -c:Release -p:BlazorWasmPrerenderingLocale=ja%2cen
  5. Improve search engine indexing for pre-rendered apps

    master

    While pre-rendering provides static HTML for crawlers, search engine bots may still attempt to download large files in the _framework directory (such as the .NET WebAssembly runtime and app assemblies). These files are unnecessary for indexing and can slow down the crawling process.

    To optimize indexing, add a robots.txt file to your wwwroot folder to disallow crawlers from accessing the _framework directory.

    User-agent: *
    Disallow: /_framework/
  6. Configure service registration for pre-rendering

    master

    To ensure your Blazor WebAssembly components work correctly during the pre-rendering process, you must extract your service registration logic into a static local function named static void ConfigureServices(IServiceCollection services, string baseAddress) within your Program.cs.

    The package looks for this specific function signature to initialize services during pre-rendering.

    Supported Signatures:

    • static void ConfigureServices(IServiceCollection services, string baseAddress): The string argument is treated as the app's base address.
    • static void ConfigureServices(IServiceCollection services, IConfiguration configuration): Uses the contents of wwwroot/appsetting.json.
    • static void ConfigureServices(IServiceCollection services, IWebAssemblyHostEnvironment webHostEnv, IConfiguration configuration): Use this if you need to access the environment name via webHostEnv.Environment or the base address via webHostEnv.BaseAddress.
    // Program.cs
    
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("#app");
    builder.RootComponents.Add<HeadOutlet>("head::after");
    
    ConfigureServices(builder.Services, builder.HostEnvironment.BaseAddress);
    
    await builder.Build().RunAsync();
    
    static void ConfigureServices(IServiceCollection services, string baseAddress)
    {
      services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) });
      services.AddScoped<IFoo, MyFoo>();
    }