top of page
Writer's pictureThe Tech Platform

ASP.NET Blazor Render Modes - A Comprehensive Guide

Welcome to our in-depth exploration of ASP.NET Blazor Render Modes. In the dynamic landscape of web development, understanding the intricacies of render modes is pivotal for creating responsive and efficient applications. This comprehensive guide is designed to provide you with a thorough understanding of the render modes offered by ASP.NET Blazor, empowering you to make well-informed decisions throughout your development journey.


ASP.NET Blazor Render Modes

Overview:

ASP.NET Blazor, a framework for building interactive web applications, offers various render modes, each with its unique characteristics. These render modes play a crucial role in determining how components are rendered and updated in the user interface.


What to Expect:

Throughout this guide, we will explore different render modes provided by ASP.NET Blazor, exploring their functionalities and use cases. From server-side rendering to client-side rendering with WebAssembly, we'll break down each mode, providing examples and best practices to guide you in choosing the most suitable approach for your projects.


Who Should Read This Guide:

  • Developers exploring ASP.NET Blazor for web application development.

  • Seasoned developers looking to deepen their understanding of Blazor render modes.

  • Decision-makers seeking insights into optimizing application performance.

Let's Begin!


Table of contents:
  1. Static Server-Side rendering (static SSR)

  2. Interactive Server-Side Rendering (Interactive SSR)

  3. Client-side Rendering (CSR)

  4. Automatic Rendering


What is Render Modes?

Blazor Render Modes control how and where Razor components are rendered, dictating their hosting environment, rendering location, and interactive capabilities. Choosing the right render mode for your app is crucial for optimizing performance, responsiveness, and user experience.


How to apply Blazor Render Mode?

There are three main ways to apply a render mode for your components:


1. Component Instance:

Use the @rendermode directive within a component tag:

<MyComponent RenderMode="Server" />

2. Component Definition:

Use the @rendermode directive with the desired render mode type above the component class declaration:

@using Microsoft.AspNetCore.Components.RenderTree

@rendermode Server
<div class="my-component">...</div>

@code {
    ...
}

The above code defines a Blazor component with server-side rendering.


Note:

  • The RenderTree namespace is used for working with component UI elements.

  • The component's HTML structure is defined within the div element.

  • The component's logic and behavior are implemented within the @code block.


3. Entire App:

Set the render mode of the Routes component in App.razor:

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>
@code {
    // Set the render mode for the entire app
    RenderMode = RenderMode.ServerPrerendered;
}

Let's understand the above code in detail:


Router Component:

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">

Sets up routing for the Blazor app, matching incoming URLs to components and rendering the appropriate content.


Attributes:

  • AppAssembly="@typeof(Program).Assembly": Specifies the assembly containing the app's components and pages to search for routes.

  • PreferExactMatches="@true": Prioritizes exact route matches over wildcards for better performance and URL specificity.


Found Context:

<Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />

Triggers: When a matching route is found.


Contents:

  • RouteView: Renders the component associated with the matched route.

  • RouteData="@routeData": Passes route data (URL parameters) to the component.

  • DefaultLayout="@typeof(MainLayout)": Applies a default layout for consistent structure.


NotFound Context:

<NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>

Triggers when no matching route is found.


Contents:

  • LayoutView: Renders a layout (typically a base template for pages).

  • Layout="@typeof(MainLayout)": Uses the specified layout (likely the same as for found routes).

  • Displays a message indicating no content for the requested URL.


@code Block:

@code {
    // Set the render mode for the entire app
    RenderMode = RenderMode.ServerPrerendered;
}

Contains C# code for the component.


RenderMode Assignment:

  • RenderMode = RenderMode.ServerPrerendered;: Sets the render mode for the entire app to server-side prerendering.

  • Components are rendered on the server as HTML, enhancing initial load speed and SEO.


Also Read:


Different Render Modes

Each render mode determines where the component is hosted, whether it is interactive, and how it is initially rendered.


Below are different render modes:

  1. Static Server-Side rendering (static SSR)

  2. Interactive Server-Side Rendering (Interactive SSR)

  3. Client-side Rendering (CSR)

  4. Automatic Rendering


1. Static Server-Side rendering (static SSR)

  • This is the default mode for Razor components.

  • The component is rendered on the server and sent to the browser as HTML.

  • There is no interactivity with the component after it is rendered.

  • This mode is the simplest and most performant, but it also provides the least flexibility.


Static Server-Side Rendering (SSR) is a render mode in Blazor Web Apps. In this mode, the components are rendered on the server and sent to the client as static HTML. However, these components are not interactive as they don’t have any client-side capabilities.


Here’s an example of how to apply a render mode to a component instance using the @rendermode Razor directive attribute:

<Dialog @rendermode="StaticServer" />

In this example, static server-side rendering (static SSR) is applied to the Dialog component instance.


Consider the below example where there is not explicit designation for the components' render mode, so it inherits the default render mode from its parent. As a result, the component is statically rendered on the server.


The button in this example is not interactive because in static server-side rendering, the components are not interactive and don’t have any client-side capabilities. Therefore, when the button is clicked, it doesn’t call the UpdateMessage method, and the value of message doesn’t change. The component isn’t rerendered in response to UI events.


Here’s the code you provided:

@page "/render-mode-1"

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not clicked yet.";

    private void UpdateMessage()
    {
        message = "Somebody clicked me!";
    }
}

In this code, the UpdateMessage method, which is intended to update the message variable when the button is clicked, won’t be triggered due to the static nature of server-side rendering. Hence, the message remains “Not clicked yet.” even after the button is clicked. This is a characteristic behavior of static server-side rendering in Blazor.


Load JavaScript in a Blazor Web App with Static with Static Server Side Rendering

Blazor's enhanced navigation is convenient for users, but it can lead to unexpected behavior with page-specific JavaScript. To ensure proper execution, avoid relying on <script> elements outside of the layout file for individual components.


Instead, follow these guidelines:

  • Register an afterWebStarted JS initializer: This function ensures JavaScript initialization occurs after Blazor has fully started.

  • Use the enhancedload event listener: This listener detects page updates triggered by enhanced navigation, allowing you to execute JavaScript code accordingly.


Consider the below example demonstrating how to configure JavaScript to run correctly when a statically rendered page with enhanced navigation is either first loaded or updated.


STEP 1: Add a PageWithScript component to your Razor component. This component will contain the JS code that you want to run.

// In your Razor component file (e.g., PageWithScript.razor) 
@page "/page-with-script" 
@using BlazorPageScript 

<PageTitle>Enhanced Load Script Example</PageTitle> <PageScript Src="./Components/Pages/PageWithScript.razor.js" /> 

Welcome to my page.

STEP 2: In the Blazor Web App, add a collocated JS file that defines the onLoad, onUpdate, and onDispose functions.

// In Components/Pages/PageWithScript.razor.js 
function onLoad() 
{ 
    console.log('Page script loaded'); 
} 

function onUpdate() 
{ 
    console.log('Page script updated'); 
} 

function onDispose() 
{ 
    console.log('Page script disposed'); 
}

STEP 3: In a Razor Class Library (RCL), add a module that registers page script elements and provides an afterWebStarted function.


Add a module in an RCL (e.g., BlazorPageScript.razor.js)

import { registerPageScriptElements, afterWebStarted } from './PageScriptModule'; 

registerPageScriptElements(); 

afterWebStarted(() => 
{ 
    console.log('Blazor started, registering for enhanced navigation events'); 
    Blazor.registerFunction('onLoad', onLoad); 
    Blazor.registerFunction('onUpdate', onUpdate); 
    Blazor.registerFunction('onDispose', onDispose);       
    Blazor.addEventListener('enhancedload', (args) => onLoad(args.detail)); 
});

STEP 4: In the RCL, add a PageScript component that references the JS file from step 2.

// In BlazorPageScript.razor 
<script src="@Src"></script>

STEP 5: If you want to reuse the same module among pages, but have the onLoad and onDispose callbacks invoked on each page change, append a query string to the end of the script so that it's recognized as a different module.

// In PageWithScript.razor
<PageScript Src="./Components/Pages/PageWithScript.razor.js?v=1" />

While server-side rendering can improve initial load performance, it might not be suitable for components that require extensive interactivity or client-side logic.


Benefits:

  • Fast initial load: Pre-rendered HTML eliminates client-side processing, minimizing initial page load times.

  • Simple implementation: Easiest mode to use, no need for additional resources or complex setups.

  • SEO-friendly: Search engines can easily crawl and index the pre-rendered content.


2. Interactive Server-Side Rendering (Interactive SSR)

  • This mode allows components to be interactive with the browser.

  • The component is initially rendered on the server and then streamed to the browser.

  • The browser can then send events back to the server to update the component.

  • This mode provides more flexibility than static SSR, but it can also be less performant.


Interactive SSR is a rendering approach in Blazor that enables components to be rendered and executed directly on the server, while maintaining a persistent, real-time connection with the browser for seamless user interactions and efficient updates.


Here's how Interactive Server-Side Rendering (SSR) is executed or operates.:

  1. User navigates to /render-mode-2 in the browser.

  2. Server renders the component's initial HTML, including the button and "Not clicked yet." message.

  3. Browser displays the component and establishes a persistent connection with the server.

  4. User clicks the button.

  5. Browser sends a signal over the connection to the server.

  6. Server executes the UpdateMessage method, updating the message variable to "Somebody clicked me!".

  7. Server re-renders the component with the new message.

  8. Server sends updated HTML for the component back to the browser.

  9. Browser seamlessly updates the displayed message without a full page reload.


Consider the below example that shows how components rendered on the server can respond to user interactions without full page reloads.

@page "/render-mode-2"
@rendermode InteractiveServer  // Specifies interactive SSR

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not clicked yet.";

    private void UpdateMessage()
    {
        message = "Somebody clicked me!";
    }
}

Explanation:

  1. @page "/render-mode-2": Defines the component's route.

  2. @rendermode InteractiveServer: Sets the render mode to interactive SSR.

  3. <button @onclick="UpdateMessage">: Renders a button that calls the UpdateMessage method when clicked.

  4. @message: Displays the current value of the message variable.

  5. @code { ... }: Contains the component's C# code.

  6. private string message = "Not clicked yet.": Initializes the message variable.

  7. private void UpdateMessage() { ... }: Method triggered by the button click.

  8. message = "Somebody clicked me!": Updates the message variable.


Practical Use:

  • Component placement: Server-side components reside in the server project's Components/Pages folder.

  • Project identification: Server project typically lacks the .Client suffix in its name.

  • Component access: Navigate to the component's route in the browser (e.g., /render-mode-2).


Best suited for:

  • Applications requiring frequent server interactions or benefiting from reduced initial load time.

  • Scenarios where server-side logic or data access is essential for component rendering.


Benefits:

  • Rich user experience: Enables real-time interaction with components without client-side limitations.

  • Reduced client-side complexity: Server-side logic handles heavy processing, keeping the client-side code more manageable.

  • Offline support: Limited functionality can be available even without an internet connection.

  • Reduced initial load time: Server renders initial HTML, improving perceived performance.

  • Enhanced responsiveness: Real-time connection enables rapid updates without full page reloads.


3. Client-side Rendering (CSR) using Blazor WebAssembly

  • This mode allows components to be run in the browser using Blazor WebAssembly.

  • The Blazor WebAssembly runtime is downloaded to the browser and then used to run the components.

  • This mode is typically used for components that need to be highly interactive or that need to work offline.

  • This mode can be the most interactive, but it also requires the most setup and can be slower to load initially.

Client-side rendering (CSR) with Blazor WebAssembly refers to a render mode that executes Blazor components directly within the user's browser, entirely on the client side.


This means:

  • No Server Round Trips: Components render and update without communicating with the server for each interaction, leading to fast and responsive user experiences.

  • WebAssembly Power: Blazor WebAssembly enables .NET code to run in the browser, making CSR possible for Blazor applications.

  • Interactive Experience: CSR allows for instant user interactions and dynamic UI updates without page reloads, enhancing user engagement.

  • Separate Client Project: CSR components must be built and deployed from a separate client project specifically configured for Blazor WebAssembly.

  • Initial Download: The browser downloads the .NET runtime and application bundle (including Blazor WebAssembly code) upon the first request, potentially impacting initial load time.

  • Offline Potential: CSR applications can be designed to function offline, providing access to features even without an internet connection.

  • Reduced Server Load: CSR can lessen the processing burden on the server, especially for highly interactive applications.


Here's how Client -Side Rendering (CSR) is executed or operates.:


STEP 1: Initial Load

The user requests the component. Browser downloads and caches the .NET runtime and app bundle (JavaScript, Blazor WebAssembly code, and resources).


Code example:

<script src="_framework/blazor.webassembly.js"></script> ```

STEP 2: Component Execution

The .NET runtime starts in the browser. Component code executes within the browser, rendering its HTML structure and content.


Code example:

@page "/render-mode-3" 
@rendermode InteractiveWebAssembly 

<button @onclick="UpdateMessage">Click me</button> @message 

@code 
{ 
	private string message = "Not clicked yet."; 

	private void UpdateMessage() 
	{ 
		message = "Somebody clicked me!"; 
	} 
}

STEP 3: User Interactions

User interactions trigger event handlers directly in the browser. Component code responds to events, updates state, and re-renders efficiently without server communication.


Practical Uses:

Highly interactive applications: CSR shines in scenarios where instant responses to user actions and dynamic UI updates are crucial, like:

  • Real-time chat applications

  • Interactive dashboards and data visualizations

  • Collaborative editing tools

  • Single-page applications (SPAs) with rich user experiences


Offline functionality: When designed properly, CSR apps can function even without an internet connection, ideal for:

  • Mobile applications accessed on the go

  • E-commerce apps for browsing and adding items to a cart offline

  • Travel booking apps for managing itineraries without constant connection


Reduced server load: CSR shifts processing tasks to the client side, alleviating pressure on the server, beneficial for:

  • High-traffic applications with many concurrent users

  • Applications with demanding real-time calculations or updates

  • Situations where server scalability needs are a concern


Best Suited Scenarios:

  • Applications prioritizing responsiveness and user engagement: Where immediate user interactions and dynamic UI updates are key to the experience.

  • Scenarios where offline access is essential: When reliable operation without an internet connection is crucial.

  • Applications experiencing server load issues: As a way to offload processing from the server and enhance scalability.

  • Developments utilizing existing .NET skills: For leveraging expertise with .NET for browser-based applications.


Benefits:

  • Improved responsiveness: Faster interactions as updates happen directly in the browser, reducing server roundtrips.

  • Offline capability: Full functionality can be available offline if properly designed and prepared.

  • Potential performance gains: Reduced reliance on the server can improve performance for highly interactive apps.


4. Automatic Rendering (Interactive Auto)

  • This render mode starts with interactive server-side rendering and then switches to client-side rendering after the Blazor bundle is downloaded.

  • This is a good option for components that need to be initially rendered quickly but also need to be interactive.

  • This mode provides a balance between performance and interactivity.


Automatic rendering means deciding how to display the component while the program is running. Initially, the component is shown using interactive server-side rendering (interactive SSR) with the Blazor Server hosting model. The .NET runtime and app bundle are downloaded to the user's device in the background and stored for later use. For components using the automatic render mode, need to be created from a different client project that sets up the Blazor WebAssembly host.


Code Example:

@page "/render-mode-4"
@rendermode InteractiveAuto

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not clicked yet.";

    private void UpdateMessage()
    {
        message = "Somebody clicked me!";
    }
}

Here's how automated Rendering is executed or operates:


STEP 1: Initial Request:

  • The component renders interactively on the server using Blazor Server.

  • Browser displays rendered content.

  • The browser starts downloading and caching .NET runtime and app bundle in the background.


STEP 2: User Interactions:

  • User interactions are handled interactively on the server (initially).

  • Component re-renders and updates UI accordingly.


STEP 3: Subsequent Visits:

  • If cached assets are available, the component switches to CSR.

  • The component renders directly in the browser for subsequent interactions.


Benefits:

  • Combines initial speed and interaction: Leverages the advantages of both SSR and CSR, balancing immediate responsiveness and overall performance.

  • Dynamic adaptation: Automatically adjusts to network conditions and user preferences, providing a seamless experience.

Pre-rendering

Prerendering refers to the process of generating a component's HTML on the server before it's sent to the client. It's a technique specifically used within certain render modes to enhance initial performance and SEO.


  • Prerendering is enabled by default for interactive components but can be disabled.

  • You can create custom render modes with specific configurations.

  • Blazor WebAssembly is required for CSR and auto-render modes.


Here are the steps to set up pre-rendering for a hosted Blazor WebAssembly app:


Host the Blazor WebAssembly app in an ASP.NET Core app. You can either add a standalone Blazor WebAssembly app to an ASP.NET Core solution or use a hosted Blazor WebAssembly app created from the Blazor WebAssembly project template with the hosted option.


Delete the wwwroot/index.html file from the Blazor WebAssembly Client project.


In the Client project, delete the following lines in Program.cs:

builder.RootComponents.Add<App> ("#app");
builder.RootComponents.Add<HeadOutlet> ("head::after");

Add _Host.cshtml file to the Server project’s Pages folder. You can obtain the files from a project created from the Blazor Server template.


Make the necessary changes to the _Host.cshtml file. Update the Pages namespace at the top of the file to match the namespace of the Server app’s pages.


Benefits of Prerendering in Blazor:

  • Faster Initial Load: The browser receives prerendered content, reducing the time it takes to display the first page or component.

  • Improved SEO: Search engines can easily index the prerendered HTML, boosting search rankings.

  • Smoother User Experience: Users see content quickly, even on slower connections.


Choosing the Right Render Mode

The ideal render mode depends on your specific application requirements. Consider factors like:

  • Performance needs: Static SSR for fast initial load, CSR for highly interactive experiences.

  • Interactivity level: Static SSR or CSR for limited interactivity, interactive SSR for real-time responsiveness.

  • Offline requirements: Interactive SSR or Auto for some offline functionality, CSR for fully offline capabilities.

  • Development complexity: Static SSR is easiest to implement, CSR and Auto might require additional setup.

By understanding the benefits and limitations of each render mode, you can make informed decisions and design optimized Blazor applications that deliver exceptional performance and user engagement.


Conclusion

In wrapping up our journey through ASP.NET Blazor Render Modes, you've gained insights into the rendering options available within this robust framework. Whether it's the efficiency of server-side rendering or the flexibility of client-side rendering with WebAssembly, each mode offers unique advantages.


Keep exploring updates, stay engaged with the community, and adapt your strategies to the evolving web development landscape.


Thank you for joining us on this exploration. Happy coding!

Comments


bottom of page