Compartilhar via


Pré-renderizar componentes Razor do ASP.NET Core

Observação

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

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

A pré-geração é o processo de renderização estatica do conteúdo da página do servidor para entregar HTML ao navegador o mais rápido possível. Depois que o conteúdo pré-gerado é exibido rapidamente para o usuário, o conteúdo interativo com manipuladores de eventos ativos é renderizado, substituindo qualquer conteúdo que foi renderizado anteriormente. A pre-renderização também pode melhorar SEO (Otimização do Mecanismo de Pesquisa) ao gerar o conteúdo da resposta HTTP inicial que os mecanismos de pesquisa usam para calcular a classificação da página.

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

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

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

Desabilitar a pré-renderização

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

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

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

Para desabilitar 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 desabilitar a pré-renderização de 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 é um componente raiz.

Para aplicativos com base no modelo de projeto do Blazor Web App, um modo de renderização atribuído a todo o aplicativo é especificado, em que o componente Routes é usado no componente App (Components/App.razor). O exemplo a seguir define o modo de renderização do aplicativo como Servidor Interativo com a pré-renderização desabilitada:

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

Além disso, desabilite 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.

Desabilitar a pré-geração usando as técnicas anteriores só entra em vigor para 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 dos respectivos filhos serão ignoradas.

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. Para obter diretrizes sobre como persistir o estado durante a pré-renderização, consulte Persistência de estado pré-renderizado no ASP.NET CoreBlazor.

Os serviços do lado do cliente falham em ser resolvidos 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 do Blazor registrados do lado do cliente, 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 este 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 runtime 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".

Esse erro ocorre porque o componente deve ser compilado e executado 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 este 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 prerenderização. Para obter um exemplo desse cenário, consulte as diretrizes para HttpClient serviços na Blazor Web App seção de APIs Web externas do artigo Chamar API Web.

Injete 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é-geração e um serviço diferente no cliente.

Por exemplo, o código a seguir obtém o ambiente do aplicativo se o código está em execução no servidor ou no cliente injetando IHostEnvironment no Microsoft.Extensions.Hosting.Abstractions 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ário.

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 abordagens a seguir.

O exemplo a seguir usa a injeção de construtor de IWebAssemblyHostEnvironment:

private string? environmentName;

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

Como alternativa, injete IServiceProvider para obter opcionalmente o serviço se ele 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. Registre os serviços em cada projeto. Insira, quando necessário, a abstração do serviço personalizado em componentes. Em seguida, o componente passa a depender apenas da abstração do serviço personalizado.

No caso de 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 Program do projeto de servidor, registre o serviço:

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

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

Desativar a prerenderização para o componente

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