Ler em inglês

Partilhar via


Pré-renderizar componentes ASP.NET Core Razor

Nota

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.

Importante

Estas informações referem-se a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.

Para a versão atual, consulte a versão .NET 9 deste artigo.

Este artigo explica Razor cenários de pré-renderização de componentes para componentes renderizados em servidor em Blazor Web Apps.

Pré-renderização consiste em renderizar previamente o conteúdo da página no servidor, sem ativar os manipuladores de eventos para controles renderizados. O servidor gera a interface HTML da página o mais rápido possível em resposta à solicitação inicial, o que faz com que o aplicativo pareça mais responsivo aos utilizadores. A pré-renderização também pode melhorar de Search Engine Optimization (SEO), renderizando conteúdo para a resposta HTTP inicial que os mecanismos de pesquisa usam para calcular o page rank.

Persistir o estado pré-renderizado

Sem guardar o estado pré-renderizado, o estado utilizado durante a pré-renderização é perdido e precisa ser recriado quando a aplicação estiver totalmente carregada. Se algum estado for criado de forma assíncrona, a UI pode piscar quando a UI pré-renderizada for substituída ao rerenderizar o componente.

Considere o seguinte componente PrerenderedCounter1 contador. O componente define um valor de contador aleatório inicial durante o processo de pré-renderização no método de ciclo de vidaem . Depois que a conexão SignalR com o cliente é estabelecida, o componente é novamente renderizado, e o valor de contagem inicial é substituído assim que OnInitialized é executado pela segunda vez.

PrerenderedCounter1.razor:

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 do componente. Segue-se um exemplo de saída.

Nota

Se a aplicação adotar o de roteamento interativo e a página for alcançada através de uma navegação interna aprimorada, a pré-renderização não ocorrerá. Portanto, você deve executar uma recarga de página inteira para o componente PrerenderedCounter1 para ver a saída a seguir. Para obter mais informações, consulte a seção de roteamento interativo e pré-renderização.

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 é rerenderizado. Há também uma cintilação na interface do usuário quando a contagem é atualizada de 41 para 92.

Para manter o valor inicial do contador durante a pré-renderização, o Blazor suporta a persistência do estado numa página pré-renderizada usando o serviço PersistentComponentState (e para componentes incorporados em páginas ou vistas de aplicações Razor Pages ou MVC, o Persist Component State Tag Helper).

Para preservar o estado pré-renderizado, decida qual estado persistir usando o serviço PersistentComponentState. PersistentComponentState.RegisterOnPersisting registra um retorno de chamada para persistir o estado do componente antes que o aplicativo seja pausado. O estado é recuperado quando o aplicativo é retomado.

O exemplo a seguir demonstra o padrão geral:

  • O espaço reservado {TYPE} representa o tipo de dados a serem persistidos.
  • O espaço reservado {TOKEN} é uma cadeia de caracteres identificadora de estado. Considere usar nameof({VARIABLE}), onde o espaço reservado {VARIABLE} é o nome da variável que contém o estado. O uso de nameof() para o identificador de estado evita o uso de uma cadeia de caracteres entre aspas.
razor
@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 mantém o estado do contador durante a pré-renderização e recupera esse estado para inicializar o componente.

PrerenderedCounter2.razor:

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, currentCount é definido apenas uma vez durante a pré-renderização. O valor é restaurado quando o componente é rerenderizado. Segue-se um exemplo de saída.

Nota

Se a aplicação adotar o de roteamento interativo e a página for alcançada através de uma navegação interna aprimorada, a pré-renderização não ocorrerá. Portanto, você deve executar uma recarga de página inteira para o componente PrerenderedCounter2 para ver a saída a seguir. Para obter mais informações, consulte a seção de roteamento interativo e pré-renderização.

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 dispendiosas são executadas apenas 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 modo de renderização InteractiveAuto combina WebAssembly e interatividade do servidor, por isso é necessário considerar a exposição de dados ao navegador, como no caso CSR.

Componentes incorporados em páginas e visualizações (Razor Pages/MVC)

Para componentes incorporados numa página ou vista de uma aplicação Razor Pages ou MVC, deves adicionar a etiqueta Persist Component State Tag Helper com a etiqueta HTML <persist-component-state /> dentro da etiqueta de fecho </body> do layout da aplicação. Isso só é necessário para Razor Pages e aplicativos MVC. Para obter mais informações, consulte Persist Component State Tag Helper no ASP.NET Core.

Pages/Shared/_Layout.cshtml:

CSHTML
<body>
    ...

    <persist-component-state />
</body>

Roteamento e pré-renderização interativos

Quando o componente Routes não define um modo de renderização, o aplicativo está usando interatividade e navegação por página/componente. Usando a navegação por página/componente, a navegação interna† é tratada por um roteamento aprimorado após o aplicativo tornar-se interativo. † interno neste contexto significa que o destino da URL do evento de navegação é um endpoint Blazor dentro da aplicação.

O serviço PersistentComponentState só funciona no carregamento inicial da página e não em eventos internos de navegação de página avançada.

Se o aplicativo executar uma navegação completa (não aprimorada) para uma página utilizando o estado de componente persistente, o estado persistente será disponibilizado para o aplicativo usar quando se tornar interativo.

Se um circuito interativo já tiver sido estabelecido e uma navegação aprimorada for realizada em uma página utilizando o estado persistente do componente, o estado não será disponibilizado no circuito existente para o componente usar. Não há pré-renderização para a solicitação de página interna e o serviço PersistentComponentState não está ciente de que ocorreu uma navegação aprimorada. Não há nenhum mecanismo para fornecer atualizações de estado para componentes que já estão em execução em um circuito existente. A razão para isso é que Blazor só suporta a passagem de estado do servidor para o cliente no momento em que o tempo de execução é inicializado, não depois que o tempo de execução é iniciado.

Trabalho adicional na estrutura de Blazor para abordar esse cenário está em consideração para o .NET 10 (novembro de 2025). Para obter mais informações e discussão na comunidade sobre soluções alternativas não suportadas‡, consulte Suportar o estado do componente persistente em navegações de página aprimoradas (dotnet/aspnetcore #51584). ‡Soluções alternativas sem suporte não são sancionadas pela Microsoft para uso em aplicativos Blazor. Use pacotes, abordagens e códigos de terceiros por sua conta e risco.

A desativação da navegação aprimorada, que reduz o desempenho, mas também evita o problema do estado de carregamento com PersistentComponentState para solicitações de página internas, é abordada no Blazorde roteamento e navegação do Core .

Orientações para pré-renderização

A orientação de pré-renderização é organizada na documentação Blazor por assunto. Os links a seguir abrangem todas as orientações de pré-renderização ao longo da documentação definida por assunto: