Representación previa de componentes de Razor de ASP.NET Core

En este artículo se explican los escenarios de representación previa de componentes de Razor para componentes representados por el servidor en Blazor Web Apps.

La representación previa es el proceso de representación inicial del contenido de la página en el servidor sin habilitar controladores de eventos para controles representados. El servidor genera la interfaz de usuario HTML de la página lo antes posible en respuesta a la solicitud inicial, lo que hace que la aplicación se sienta más sensible a los usuarios. La representación previa también puede mejorar la optimización del motor de búsqueda (SEO) mediante la representación del contenido de la respuesta HTTP inicial que los motores de búsqueda usan para calcular la clasificación de página.

Conservación del estado previamente representado

Si no se conserva el estado representado previamente, se pierde el estado usado durante la representación previa, por lo que se debe volver a crear una vez que la aplicación se haya cargado por completo. Si se crea un estado de forma asincrónica, la interfaz de usuario puede parpadear a medida que se reemplaza la interfaz de usuario prerepresentada cuando se vuelve a representar el componente.

Tenga en cuenta el siguiente componente de contador PrerenderedCounter1. El componente establece un valor de contador aleatorio inicial durante la representación previa en el método de ciclo de vida OnInitialized. Una vez establecida la conexión SignalR al cliente, el componente vuelve a representarse y el valor de recuento inicial se reemplaza cuando OnInitialized se ejecuta una 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++;
    }
}

Ejecute la aplicación e inspeccione el registro desde el componente. A continuación se incluye el resultado del ejemplo.

Nota:

Si la aplicación adopta el enrutamiento interactivo (mejorado) y la página se alcanza a través de una navegación interna, no se produce la representación previa. Por lo tanto, debe realizar una recarga de página completa para el PrerenderedCounter1 componente para ver la salida siguiente.

info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 41
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 92

El primer recuento registrado se produce durante la representación previa. El recuento se establece de nuevo tras la representación previa cuando se vuelve a representar el componente. También hay un parpadeo en la interfaz de usuario cuando el recuento se actualiza de 41 a 92.

Para conservar el valor inicial del contador durante la representación previa, Blazor es compatible con la persistencia del estado en una página con representación previa usando el servicio PersistentComponentState (y para componentes incrustados en páginas o vistas de Razor Pages o aplicaciones MVC, el Ayudante de etiqueta de estado de componentes persistentes).

Para preservar el estado de representación previa, decida qué estado mantener usando el servicio de PersistentComponentState. PersistentComponentState.RegisterOnPersisting registra una devolución de llamada para conservar el estado del componente antes de que se pause la aplicación. El estado se recupera cuando se reanuda la aplicación.

En el ejemplo siguiente, se muestra el patrón general:

  • El marcador de posición {TYPE} representa el tipo de datos que se va a conservar.
  • El marcador de posición {TOKEN} es una cadena de identificador de estado. Considere la posibilidad de usar nameof({VARIABLE}), donde el marcador de posición {VARIABLE} es el nombre de la variable que contiene el estado. El uso de nameof() del identificador de estado evita el uso de una cadena entre comillas.
@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();
    }
}

El siguiente ejemplo de componente de contador conserva el estado del contador durante la representación previa y recupera el estado para inicializar el 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++;
    }
}

Cuando se ejecuta el componente, currentCount solo se establece una vez durante la representación previa. El valor se restaura cuando se vuelve a representar el componente. A continuación se incluye el resultado del ejemplo.

Nota:

Si la aplicación adopta el enrutamiento interactivo y se alcanza la página a través de una navegación interna, no se produce la representación previa. Por lo tanto, debe realizar una recarga de página completa para el PrerenderedCounter2 componente para ver la salida siguiente.

info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount restored to 96

Al inicializar componentes con el mismo estado que se usa durante la representación previa, los pasos de inicialización costosos solo se ejecutan una vez. La interfaz de usuario representada también coincide con la que se ha representado previamente, por lo que no se produce ningún parpadeo en el explorador.

Componentes incrustados en páginas y vistas (Razor Pages/MVC)

Para componentes incrustados en una página o vista de Razor Pages o una aplicación MVC, debe agregar el Ayudante de etiqueta de estado de componente persistente con la etiqueta <persist-component-state /> HTML dentro de la etiqueta de cierre </body> del diseño de la aplicación. Esto solo es necesario para Razor Pages y aplicaciones MVC. Para más información, consulte Ayudante de etiqueta de estado de componente persistente en ASP.NET Core.

Pages/Shared/_Layout.cshtml:

<body>
    ...

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

Enrutamiento interactivo y representación previa

La navegación interna para el enrutamiento interactivo no implica solicitar contenido de página nuevo desde el servidor. Por lo tanto, la representación previa no se produce para las solicitudes de página internas.

El PersistentComponentState servicio solo funciona en la carga de página inicial y no en eventos de navegación de página mejorados. Si la aplicación realiza una navegación completa (no mejorada) a una página que usa el estado de componente persistente, el estado persistente está disponible para que la aplicación la use cuando se vuelva interactiva. Pero si ya se ha establecido un circuito interactivo y se realiza una navegación mejorada a una página que representa el estado de componente persistente, ese estado no está disponible en el circuito existente. Actualmente, el servicio PersistentComponentState desconoce la navegación mejorada, y no hay ningún mecanismo para entregar actualizaciones de estado a los componentes que ya están en ejecución.

Guía de representación previa

La guía de representación previa está organizada en la documentación de Blazor por temas. En los vínculos siguientes se tratan todas las instrucciones de representación previa en toda la documentación establecida por tema: