Partilhar via


Pré-renderizar componentes ASP.NET Core Razor

Observação

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

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

A pré-renderização é o processo de renderizar estaticamente o conteúdo da página do servidor para entregar HTML ao navegador o mais rápido possível. Depois que o conteúdo pré-renderizado é exibido rapidamente para o usuário, o conteúdo interativo com manipuladores de eventos ativos é renderizado, substituindo qualquer conteúdo que tenha sido renderizado anteriormente. A pré-renderização também pode melhorar o Search Engine Optimization (SEO), renderizando conteúdo para a resposta HTTP inicial que os mecanismos de pesquisa usam para calcular o page rank.

A pré-renderização é habilitada por padrão para componentes interativos.

A navegação interna com roteamento interativo não usa pré-renderização porque a página já é interativa. Para obter mais informações, consulte Roteamento estático versus interativo e Roteamento e pré-renderização interativos.

OnAfterRender{Async} Os eventos do ciclo de vida do componente não são chamados durante a pré-renderização, somente depois que o componente é renderizado interativamente.

Desativar pré-renderização

A pré-renderização pode complicar um aplicativo porque os Razor componentes do aplicativo devem renderizar duas vezes: uma para pré-renderização e outra para configurar a interatividade. Se os componentes estão configurados para serem executados no WebAssembly, você também deve projetar seus componentes para que eles possam ser executados a partir do servidor e do cliente.

Para desativar a pré-renderização de uma instância de componente , passe o sinalizador prerender com um valor de false no modo de renderização.

  • <... @rendermode="new InteractiveServerRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveAutoRenderMode(prerender: false)" />

Para desativar a pré-renderização em uma definição de componente :

  • @rendermode @(new InteractiveServerRenderMode(prerender: false))
  • @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
  • @rendermode @(new InteractiveAutoRenderMode(prerender: false))

Para desativar a pré-renderização para todo o aplicativo, indique o modo de renderização no componente interativo de nível mais alto na hierarquia de componentes do aplicativo que não seja um componente raiz.

Para aplicativos baseados no modelo de projeto Blazor Web App, um modo de renderização atribuído ao aplicativo inteiro é especificado onde o componente Routes é usado no componente App (Components/App.razor). O exemplo a seguir define o modo de renderização do aplicativo como Interactive Server com a pré-renderização desabilitada:

<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Além disso, desative a pré-renderização para o componente HeadOutlet no componente App:

<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Não há suporte para tornar um componente raiz, como o componente App, interativo com a diretiva @rendermode na parte superior do arquivo de definição do componente raiz (.razor). Portanto, a pré-renderização não pode ser desabilitada diretamente pelo componente App.

A desativação da pré-renderização usando as técnicas anteriores só tem efeito para os modos de renderização de nível superior. Se um componente pai especificar um modo de renderização, as configurações de pré-renderização de seus filhos serão ignoradas.

Manter 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. Para obter orientação sobre como persistir o estado durante a pré-renderização, consulte ASP.NET Persistência do estado pré-renderizado principalBlazor.

Os serviços do lado do cliente falham na resolução durante a pré-renderização

Supondo que a pré-renderização não esteja desabilitada para um componente ou para o aplicativo, um componente no projeto .Client é pré-renderizado no servidor. Como o servidor não tem acesso a serviços de Blazor do lado do cliente registrados, não é possível injetar esses serviços em um componente sem receber um erro de que o serviço não pode ser encontrado durante a pré-renderização.

Por exemplo, considere o seguinte componente Home no projeto .Client em um Blazor Web App com WebAssembly interativo global ou renderização automática interativa. O componente tenta injetar IWebAssemblyHostEnvironment para obter o nome do ambiente.

@page "/"
@inject IWebAssemblyHostEnvironment Environment

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    Environment: @Environment.Environment
</p>

Nenhum erro de tempo de compilação ocorre, mas ocorre um erro de tempo de execução durante a pré-renderização:

Não é possível fornecer um valor para a propriedade 'Environment' no tipo 'BlazorSample.Client.Pages.Home'. Não há nenhum serviço registrado do tipo 'Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment'.

Este erro ocorre porque o componente deve compilar e executar no servidor durante a pré-renderização, mas IWebAssemblyHostEnvironment não é um serviço registrado no servidor.

Considere qualquer uma das seguintes abordagens para resolver esse cenário:

Registrar o serviço no servidor, além do cliente

Se o serviço suportar a execução do servidor, registre o serviço no servidor, além do cliente, para que ele esteja disponível durante a pré-renderização. Para obter um exemplo desse cenário, consulte as HttpClient diretrizes para Blazor Web App serviços na seção APIs da Web externas do artigo Chamar API da Web.

Injetar um serviço que o aplicativo pode usar durante a pré-renderização

Em alguns casos, o aplicativo pode usar um serviço no servidor durante a pré-renderização e um serviço diferente no cliente.

Por exemplo, o código a seguir obtém o ambiente do aplicativo, independentemente de o código estar sendo executado no servidor ou no cliente, ao injetar a partir do pacote NuGet .

private string? environmentName;

public Home(IHostEnvironment? serverEnvironment = null, 
    IWebAssemblyHostEnvironment? wasmEnvironment = null)
{
    environmentName = serverEnvironment?.EnvironmentName;
    environmentName ??= wasmEnvironment?.Environment;
}

No entanto, essa abordagem adiciona uma dependência adicional ao projeto cliente que não é necessária.

Tornar o serviço opcional

Torne o serviço opcional se ele não for necessário durante a pré-renderização usando uma das seguintes abordagens.

O exemplo seguinte utiliza injeção de construtor de IWebAssemblyHostEnvironment:

private string? environmentName;

public Home(IWebAssemblyHostEnvironment? env = null)
{
    environmentName = env?.Environment;
}

Em alternativa, injete IServiceProvider para obter opcionalmente o serviço, se estiver disponível:

@page "/"
@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IServiceProvider Services

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    <b>Environment:</b> @environmentName
</p>

@code {
    private string? environmentName;

    protected override void OnInitialized()
    {
        if (Services.GetService<IWebAssemblyHostEnvironment>() is { } env)
        {
            environmentName = env.Environment;
        }
    }
}

Criar uma abstração de serviço

Se uma implementação de serviço diferente for necessária no servidor, crie uma abstração de serviço e crie implementações para o serviço nos projetos de servidor e cliente. Registe os serviços em cada projeto. Injete a abstração de serviço personalizado nos componentes onde necessário. O componente, então, depende exclusivamente da abstração de serviço personalizado.

No caso do IWebAssemblyHostEnvironment, podemos reutilizar a interface existente em vez de criar uma nova:

ServerHostEnvironment.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.AspNetCore.Components;

public class ServerHostEnvironment(IWebHostEnvironment env, NavigationManager nav) : 
    IWebAssemblyHostEnvironment
{
    public string Environment => env.EnvironmentName;
    public string BaseAddress => nav.BaseUri;
}

No arquivo do Program do projeto do servidor, registe o serviço:

builder.Services.TryAddScoped<IWebAssemblyHostEnvironment, ServerHostEnvironment>();

Neste ponto, o IWebAssemblyHostEnvironment serviço pode ser injetado em um componente interativo WebAssembly ou Auto que também é pré-renderizado a partir do servidor.

Desativar a pré-renderização para o componente

Desative a pré-renderização para o componente ou para todo o aplicativo. Para obter mais informações, consulte a seção Desabilitar pré-renderização .