-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Docs for "Static server-side rendering guidance for Blazor component library owners" #31066
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Sure thing ... I'll create a docs issue and get to it ...... mmmmm 🤔 ... Tuesday .... I think. |
@guardrex Cool, no particular rush here, just adding it to the pipeline. |
I have been having a play with SSR, trying to convert an existing server size blazor components to static ones. One work around that I found was to replace @OnClick events with EditForm form submission and client javascript. For example, an anchor tag with an @OnClick event can is replaced with client javascript which updates a hidden field and submits the form. The server can then process the form fields and return an updated model. |
This is to implement dotnet/aspnetcore#47624
I'm proposing the following content below. @guardrex, is this something you could copy-edit and do whatever refinements you think are needed, and add to the 8.0 docs?
Component Libraries and Static Server-side Rendering (SSR)
Blazor encourages an ecosystem of open-source and commercial component libraries. Developers might also create reusable components to be shared privately across multiple applications within their own companies. Ideally, these components will be compatible with as many hosting models and rendering modes as possible. Static server-side rendering introduces additional restrictions and so can be more challenging to support than interactive rendering modes based on Blazor Server or Blazor WebAssembly.
This document provides guidance for component authors considering whether and how to support Static Server-side Rendering (SSR).
Understand the capabilities and restrictions of Static Server-side Rendering
Static server-side rendering is a mode in which components run when the server handles an incoming HTTP request. Blazor renders the component as HTML, which is included in the response. Once the response is sent, the server-side component and renderer state is discarded, so all that remains is HTML in the browser.
The benefit of this mode is cheaper, more scalable hosting, because no ongoing server resources are needed to hold component state, no ongoing connection must be maintained between browser and server, and no WebAssembly payload is required in the browser.
The cost of this mode is that event handlers such as
@onclick
cannot be run, because there is no .NET code in the browser to run them, and the server has immediately discarded any component and renderer state that would be needed to execute event handlers or to re-render the same component instances.How interactive components behave by default under Static Server-side Rendering
There are many existing Blazor components built with the assumption that events such as
@onclick
will execute handler logic. By default, all these existing components can still be used with static server-side rendering, however they will only emit their initial HTML, and their event handlers will not fire (with the special exception of@onsubmit
- see below). This is equivalent to what those components have always done when being prerendered, before any Blazor Server circuit or Blazor WebAssembly runtime was started.For components whose only role is to produce readonly DOM content, this is already completely sufficient. But for components whose role is to have interactive behaviors, the author must consider what to do.
Options for component authors
There are three main choices available:
(Simple) Don't use any interactive behaviors
For components whose only role is to produce read-only DOM content, the developer need not take any special action. These components will naturally work with any render mode. Examples:
<video>
element, making it more convenient to use from Blazor.(Simple) Require interactive rendering
You can choose to require that your component is only used with interactive rendering. This limits the applicability of your component, but means that you may freely rely on arbitrary event handlers. Even then, you should still avoid declaring a specific
@rendermode
, so the application author is free to select one. Examples:(Advanced) Use interactive behaviors, but design for static SSR and progressive enhancement
Many interactive behaviors can implemented using only HTML capabilities. With a good understanding of HTML and CSS, you can often produce a useful baseline of functionality that will work with static SSR. You can still declare event handlers that implement more advanced, optional behaviors, which will only work in interactive render modes. Examples:
<a>
links), but when used with interactive rendering may add live sorting and filtering.<a>
links and state is held only in URL query parameters, this can work without needing@onclick
.<input type=file>
, but when used with interactive rendering it could also display upload progress.In any of these strategies, there's also the option of implementing some interactive features using JavaScript.
To choose among all these options, reusable Razor component authors must make a cost/benefit tradeoff. Your component will be more useful and have a broader potential user base if it supports all render modes including static SSR, but it takes more work to design and implement a component that supports and takes best advantage of each render mode.
When to use the @rendermode directive
In almost all cases, reusable component authors should not specify a render mode at all, even when interactivity is required. This is because the component author does not know whether the application will enable support for
InteractiveServer
,InteractiveWebAssembly
, or both. By not specifying any@rendermode
, the component author leaves the choice to the application developer.Even if the component author thinks that interactivity is required, there may still be cases where an application author considers it sufficient to use static SSR alone. For example, a draggable, zoomable map component may seem to require interactivity, but in some scenario an application author may consider it useful just to render a static map image and does not need the drag/zoom behaviors.
The only reason why a reusable component author should use the
@rendermode
directive on their component is if the implementation is fundamentally coupled to one specific render mode and would certainly cause an error if used in a different mode. For example, if a component's core purpose is to interact directly with the host OS using Windows or Linux-specific APIs - in that case it may be impossible to use on WebAssembly, and so it may be reasonable to declare@rendermode InteractiveServer
.Using streaming rendering
Reusable Razor components are free to declare
@attribute [StreamRendering]
. This will result in incremental UI updates during static SSR. Since the same data loading patterns produce incremental UI updates during interactive render modes (regardless of theStreamRendering
attribute), the component can behave correctly in all cases. Even in cases where streaming SSR is suppressed on the server, the component will still render its correct final state.Using links across all render modes
Reusable Razor components may use links and enhanced navigation. HTML
<a>
tags should produce equivalent behaviors with or without an interactive<Router>
component, and whether or not enhanced navigation is enabled/disabled at an ancestor level in the DOM.Using forms across all render modes
Reusable Razor components may include forms (either
<form @onsubmit=...>
or<EditForm OnValidSubmit=...>
), as these can be implemented to work equivalently across both static and interactive render modes. Example:In this example, the
Enhance
,FormName
,method="post"
andSupplyParameterFromForm
APIs are only used during static SSR, and are ignored during interactive rendering. The form will work during both interactive and static rendering.Avoiding APIs that are specific to static SSR
To make a reusable component that works across all render modes, do not rely on
HttpContext
, because it is only available during static SSR. TheHttpContext
API would not make sense to use during Server or WebAssembly rendering, because at those times there is no active HTTP request in flight, so it is meaningless to think about setting a status code or writing to the response.Reusable components are free to receive an
HttpContext
when available, as follows:The value will be
null
during interactive rendering, and will only be set during static SSR.In many cases, there are better alternatives than using
HttpContext
. For example, if you need to know the current URL, or to perform a redirection, use the APIs onNavigationManager
since they work on all render modes, both static and interactive. Likewise, if you need to know the user's authentication status, then instead of usingHttpContext.User
, prefer to use Blazor'sAuthenticationStateProvider
service.The text was updated successfully, but these errors were encountered: