Pré-renderizar componentes Razor do ASP.NET Core
Este artigo explica os cenários de pré-renderização dos componentes Razor para os componentes renderizados pelo servidor nos Blazor Web Apps.
A pré-renderização é o processo de renderizar inicialmente o conteúdo da página no servidor sem habilitar manipuladores de eventos para controles renderizados. O servidor gera a interface do usuário HTML da página o mais rápido possível em resposta à solicitação inicial, o que dá a sensação de que o aplicativo é mais responsivo aos usuários. A pré-renderização também pode melhorar a SEO (Otimização do Mecanismo de Pesquisa) ao renderizar conteúdos de resposta ao HTTP inicial no quais os mecanismos de pesquisa usam para calcular a classificação da página.
Persistência do estado pré-renderizado
Sem a persistência do estado pré-renderizado, há perda do estado usado durante a pré-renderização e ele deve ser recriado quando o aplicativo for totalmente carregado. Se qualquer estado for criado de maneira assíncrona, a interface do usuário poderá piscar à medida que a interface do usuário pré-renderizada for substituída quando o componente for renderizado novamente.
Considere o componente de contador PrerenderedCounter1
a seguir. O componente define um valor de contador aleatório inicial durante a pré-renderização no método OnInitialized
do ciclo de vida. Depois que a conexão de SignalR com o cliente é estabelecida, o componente é renderizado novamente e o valor de contagem inicial é substituído quando OnInitialized
é executado uma segunda vez.
PrerenderedCounter1.razor
:
@page "/prerendered-counter-1"
@rendermode @(new InteractiveServerRenderMode(prerender: true))
@inject ILogger<PrerenderedCounter1> Logger
<PageTitle>Prerendered Counter 1</PageTitle>
<h1>Prerendered Counter 1</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
protected override void OnInitialized()
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
private void IncrementCount() => currentCount++;
}
Execute o aplicativo e inspecione o log no componente. A seguir está a saída de exemplo:
Observação
Se o aplicativo adotar o roteamento interativo (aprimorado) e a página for acessada por meio de uma navegação interna, a pré-renderização não ocorrerá. Portanto, você deve executar um recarregamento completo da página para que o componente PrerenderedCounter1
veja a saída a seguir.
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 41
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 92
A primeira contagem registrada ocorre durante a pré-renderização. A contagem é definida novamente após a pré-renderização quando o componente é renderizado novamente. Há também uma cintilação na interface do usuário quando a contagem é atualizada de 41 para 92.
Para reter o valor inicial do contador durante a pré-renderização, o Blazor dá suporte ao estado persistente em uma página pré-renderizada por meio do serviço PersistentComponentState (e para os componentes incorporados em páginas ou exibições de aplicativos MVC ou Razor Pages, o Auxiliar de Marcas para Persistência do Estado de Componentes).
Para preservar o estado pré-renderizado, decida qual estado será persistido por meio do serviço PersistentComponentState. PersistentComponentState.RegisterOnPersisting registra um retorno de chamada para a persistência do estado do componente antes que o aplicativo seja pausado. O estado é recuperado com a retomada do aplicativo.
O seguinte exemplo demonstra o padrão geral:
- O espaço reservado
{TYPE}
representa o tipo de dados a ser persistido. - O espaço reservado
{TOKEN}
é uma cadeia de caracteres de identificador de estado. Considere usarnameof({VARIABLE})
, em que o espaço reservado{VARIABLE}
é o nome da variável que mantém o estado. Usarnameof()
para o identificador de estado evita o uso de uma cadeia de caracteres entre aspas.
@implements IDisposable
@inject PersistentComponentState ApplicationState
...
@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
O exemplo de componente de contador a seguir persiste o estado do contador durante a pré-renderização e recupera o estado para inicializar o componente.
PrerenderedCounter2.razor
:
@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState
<PageTitle>Prerendered Counter 2</PageTitle>
<h1>Prerendered Counter 2</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
private PersistingComponentStateSubscription persistingSubscription;
protected override void OnInitialized()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistCount);
if (!ApplicationState.TryTakeFromJson<int>(
nameof(currentCount), out var restoredCount))
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
else
{
currentCount = restoredCount!;
Logger.LogInformation("currentCount restored to {Count}", currentCount);
}
}
private Task PersistCount()
{
ApplicationState.PersistAsJson(nameof(currentCount), currentCount);
return Task.CompletedTask;
}
void IDisposable.Dispose() => persistingSubscription.Dispose();
private void IncrementCount() => currentCount++;
}
Quando o componente é executado, a currentCount
é definida apenas uma vez durante a pré-renderização. O valor é restaurado quando o componente é renderizado novamente. A seguir está a saída de exemplo:
Observação
Se o aplicativo adotar o roteamento interativo e a página for acessada por meio de uma navegação interna, a pré-renderização não ocorrerá. Portanto, você deve executar um recarregamento completo de página para que o componente PrerenderedCounter2
veja a saída a seguir.
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount restored to 96
Ao inicializar componentes com o mesmo estado usado durante a pré-renderização, todas as etapas de inicialização dispendiosa só são executadas uma vez. A interface do usuário renderizada também corresponde à interface do usuário pré-renderizada, portanto, nenhuma cintilação ocorre no navegador.
O estado pré-renderizado persistente é transferido para o cliente, onde é usado para restaurar o estado do componente. Durante a renderização do lado do cliente (CSR, InteractiveWebAssembly
), os dados são expostos ao navegador e não devem conter informações confidenciais e privadas. Durante a renderização interativa do lado do servidor (SSR interativo), InteractiveServer
ASP.NET Core Data Protection garante que os dados sejam transferidos com segurança. O InteractiveAuto
modo de renderização combina WebAssembly e interatividade do servidor, por isso é necessário considerar a exposição de dados ao navegador, como no caso de CSR.
Componentes inseridos em páginas e exibições (Páginas/MVC Razor)
Para os componentes incorporados em uma página ou em uma exibição de um aplicativo MVC ou Razor Pages, adicione o Auxiliar de Marcas para Persistência do Estado de Componentes com a marca HTML <persist-component-state />
dentro da marca </body>
de fechamento do layout do aplicativo. Isso só é necessário em aplicativos MVC e Razor Pages. Para obter mais informações, confira Auxiliar de Marcas para Persistência do Estado de Componentes no ASP.NET Core.
Pages/Shared/_Layout.cshtml
:
<body>
...
<persist-component-state />
</body>
Roteamento interativo e pré-renderização
A navegação interna para roteamento interativo não envolve a solicitação de novo conteúdo de página do servidor. Portanto, a pré-renderização não ocorre para solicitações de páginas internas.
O serviço PersistentComponentState só funciona no carregamento inicial da página e não em eventos de navegação de página aprimorados. Se o aplicativo executar uma navegação completa (não aprimorada) para uma página que utiliza estado do componente persistente, o estado persistido fica disponível para o aplicativo usar quando ele se tornar interativo. Mas se um circuito interativo já foi estabelecido e uma navegação aprimorada é executada para uma página que renderiza estado do componente persistido, esse estado fica disponível no circuito existente. O serviço PersistentComponentState não reconhece a navegação aprimorada e não há nenhum mecanismo para fornecer atualizações de estado aos componentes que já estão em execução.
Diretrizes de pré-renderização
As diretrizes de pré-renderização são organizadas na documentação do Blazor por assunto. Os seguintes links abrangem todas as diretrizes de pré-renderização em toda a documentação definidas por assunto:
Conceitos básicos
Componentes
- Controlar o conteúdo de
<head>
durante a pré-renderização - Razorobjetos do ciclo de vida do componente que são pertencentes à pré-renderização
- inicialização de componente (
OnInitialized{Async}
) - após a renderização do componente (
OnAfterRender{Async}
) - Reconexão com o estado após a pré-renderização
- Pré-renderização com interoperabilidade JavaScript: esta seção também aparece nos dois artigos de interoperabilidade JS sobre como chamar o JavaScript no .NET e o .NET no JavaScript.
- inicialização de componente (
- Aplicativo de exemplo do componente QuickGrid: o aplicativo de exemplo QuickGrid para Blazor é hospedado no GitHub Pages. O site é carregado rapidamente graças à pré-geração estática usando o projeto
BlazorWasmPrerendering.Build
do GitHub mantido pela comunidade. - Pré-renderização ao integrar componentes a aplicativos MVC e Razor Pages
- Controlar o conteúdo de
Autenticação e autorização
Gerenciamento de estado: processar pré-renderização: além da seção Processar pré-renderização, várias das outras seções do artigo incluem comentários sobre pré-renderização.