Prérendu des composants ASP.NET Core Razor

Cet article explique les scénarios de prérendu des composants Razor pour les composants rendus par serveur dans les Web Apps Blazor.

Le prérendu est le processus de rendu initial du contenu d’une page sur le serveur sans activation des gestionnaires d’événements pour les contrôles rendus. Le serveur génère l’interface utilisateur HTML de la page dès que possible en réponse à la demande initiale, ce qui rend l’application plus réactive pour les utilisateurs. Le prérendu peut aussi améliorer l’optimisation du référencement d’un site auprès d’un moteur de recherche (SEO) en rendant le contenu de la réponse HTTP initiale qui est utilisée par les moteurs de recherche pour calculer le rang de la page.

Conserver l’état prérendu

Si l’état utilisé durant le prérendu n’est pas conservé, il est perdu et doit être recréé lorsque l’application est entièrement chargée. Si un état est créé de façon asynchrone, l’interface utilisateur peut scintiller pendant que l’IU prérendue est remplacée alors que le composant régénère le rendu.

Considérez le compteur de composants PrerenderedCounter1 suivant. Le composant définit une valeur de compteur aléatoire initiale pendant un prérendu dans une méthode de cycle de vie OnInitialized. Une fois la connexion SignalR avec le client établie, le composant régénère le rendu et la valeur du compteur initiale est remplacée lorsque OnInitialized s’exécute une seconde fois.

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++;
    }
}

Exécutez l’application et inspectez la journalisation à partir du composant. Voici un exemple de sortie.

Remarque

Si l’application adopte un routage interactif (amélioré) et que la page est atteinte par le biais d’une navigation interne, le prérendu ne se produit pas. Par conséquent, vous devez effectuer un rechargement de page complet pour que le composant PrerenderedCounter1 affiche la sortie suivante.

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

Le premier compte journalisé a lieu lors du prérendu. Le compte est à nouveau défini après le prérendu lorsque le composant régénère le rendu. Un scintillement dans l’interface utilisateur est également possible lorsque le compte passe de 41 à 92.

Pour conserver la valeur initiale du compteur lors du prérendu, Blazor prend en charge l’état persistant dans une page prérendue à l’aide du service PersistentComponentState (et pour les composants incorporés dans des pages ou des vues d’applications Razor Pages ou MVC, via le Tag Helper d’état du composant persistant).

Pour conserver l’état prérendu, décidez de l’état à conserver à l’aide du service PersistentComponentState. PersistentComponentState.RegisterOnPersisting enregistre un rappel pour conserver l’état du composant avant que l’application ne soit suspendue. L’état est récupéré lorsque l’application reprend.

L’exemple suivant illustre le modèle général :

  • L’espace réservé {TYPE} représente le type de données à conserver.
  • L’espace réservé {TOKEN} est une chaîne de l’identificateur d’état. Envisagez d’utiliser nameof({VARIABLE}), où l’espace réservé {VARIABLE} est le nom de la variable qui contient l’état. L’utilisation de nameof() pour l’identifiant de l’État permet d’éviter l’utilisation d’une chaîne de caractères entre guillemets.
@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();
    }
}

Le composant compteur suivant conserve l’état du compteur pendant le prérendu, puis récupère l’état pour initialiser le composant.

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++;
    }
}

Lorsque le composant s’exécute, currentCount n’est défini que lors du prérendu. La valeur est restaurée lors du nouveau rendu du composant. Voici un exemple de sortie.

Remarque

Si l’application adopte un routage interactif et que la page est atteinte par le biais d’une navigation interne, le prérendu ne se produit pas. Par conséquent, vous devez effectuer un rechargement de page complet pour que le composant PrerenderedCounter2 affiche la sortie suivante.

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

En initialisant des composants avec le même état que celui utilisé durant le prérendu, toutes les étapes d’initialisation coûteuses ne sont exécutées qu’une seule fois. L’interface utilisateur rendue correspond également à l’interface utilisateur prérendue, de sorte qu’aucun scintillement ne se produit dans le navigateur.

Composants incorporés dans des pages et des vues (MVC/Pages Razor)

Pour les composants incorporés dans une page ou une vue d’une application Razor Pages ou MVC, vous devez ajouter le Tag Helper d’état du composant persistant avec la balise HTML <persist-component-state /> à l’intérieur de la balise fermante </body> du layout de l’application. Cela n’est nécessaire que pour les applications Razor Pages et MVC. Pour plus d’informations, consultez l’assistance Tag Helper d’état du composant persistant dans ASP.NET Core.

Pages/Shared/_Layout.cshtml :

<body>
    ...

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

Routage interactif et prérendu

La navigation interne pour le routage interactif n’implique pas de demander le nouveau contenu de la page auprès du serveur. Par conséquent, un prérendu n’est pas effectué pour les demandes de pages internes.

Le service PersistentComponentState fonctionne uniquement au chargement initial de la page et non sur les événements de navigation de page améliorés. Si l’application effectue une navigation complète (non améliorée) vers une page utilisant l’état du composant persistant, l’état persistant est mis à la disposition de l’application lorsqu’elle devient interactive. Toutefois, si un circuit interactif a déjà été établi et qu’une navigation améliorée est effectuée sur une page qui rend l’état du composant persistant, cet état n’est pas mis à disposition dans le circuit existant. Actuellement, le service PersistentComponentState ne connaît pas la navigation améliorée, et il n’existe aucun mécanisme permettant de fournir des mises à jour d’état aux composants déjà en cours d’exécution.

Conseils de prérendu

Les conseils de prérendu sont organisés par sujets dans la documentation de Blazor. Les liens suivants couvrent tous les conseils de prérendu dans la documentation organisée par sujets :