Partager via


Prérendre des composants ASP.NET Core Razor

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.

Importante

Ces informations concernent un produit en préversion qui peut être substantiellement modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 9 de cet article.

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

Le prérendu est le processus de rendu initial du contenu de la page sur le serveur sans activer les 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 également améliorer l’optimisation du référencement d’un site auprès d’un moteur de recherche (SEO) en affichant le contenu de la réponse HTTP initiale utilisée par les moteurs de recherche pour calculer l’ordre de priorité 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 manière asynchrone, l'interface utilisateur peut scintiller car l'interface prérendu est remplacée lorsque le composant est rendu.

Considérez le composant de compteur PrerenderedCounter1 suivant. Le composant définit une valeur de compteur aléatoire initiale pendant le prérendu dans la méthode de cycle de vie OnInitialized. Après l'établissement de la connexion SignalR avec le client, le composant est re-rendu et la valeur initiale du compteur 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 le routage interactif et que la page est atteinte via une navigation interne améliorée , le prérendering ne se produit pas. Par conséquent, vous devez effectuer un rechargement de page complet pour que le composant PrerenderedCounter1 affiche la sortie suivante. Pour plus d'informations, voir la section Routage interactif et pré-rendu.

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

Le premier comptage journalisé a lieu pendant le prérendu. Le compteur est à nouveau défini après le prérendu lorsque le composant est rerendu. Un scintillement dans l’interface utilisateur est également possible lorsque le compte passe de 41 à 92.

Pour conserver la valeur initiale du compteur pendant le prérendu, Blazor prend en charge la persistance de l'état dans une page prérendue à l'aide du service PersistentComponentState (et pour les composants intégrés dans des pages ou des vues de pages Razor ou d'applications MVC, l'aide à la balise Persist Component State).

Pour conserver l’état préréenderé, utilisez l’attribut [SupplyParameterFromPersistentComponentState] pour conserver l’état dans les propriétés. Les propriétés dotées de cet attribut sont automatiquement persistées à l'aide du service PersistentComponentState pendant le prérendu. L’état est récupéré lorsque le composant s’affiche de manière interactive ou que le service est instancié.

Par défaut, les propriétés sont sérialisées à l’aide du System.Text.Json sérialiseur avec les paramètres par défaut. La sérialisation n'est pas sûre vis-à-vis de la découpe et nécessite la conservation des types de données utilisés. Pour plus d’informations, consultez Configurer l’outil de suppression pour Blazor ASP.NET Core.

Le composant de compteur suivant conserve l’état du compteur pendant le prérémlage et récupère l’état pour initialiser le composant :

  • L’attribut [SupplyParameterFromPersistentComponentState] est appliqué au CounterState type (State).
  • L’état du compteur est attribué lorsque null dans OnInitialized et restauré automatiquement lorsque le composant est rendu de manière interactive.

PrerenderedCounter2.razor :

@page "/prerendered-counter-2"
@inject ILogger<PrerenderedCounter2> Logger

<PageTitle>Prerendered Counter 2</PageTitle>

<h1>Prerendered Counter 2</h1>

<p role="status">Current count: @State?.CurrentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    [SupplyParameterFromPersistentComponentState]
    public CounterState? State { get; set; }

    protected override void OnInitialized()
    {
        if (State is null)
        {
            State = new() { CurrentCount = Random.Shared.Next(100) };
            Logger.LogInformation("CurrentCount set to {Count}", 
                State.CurrentCount);
        }
        else
        {
            Logger.LogInformation("CurrentCount restored to {Count}", 
                State.CurrentCount);
        }
    }

    private void IncrementCount()
    {
        if (State is not null)
        {
            State.CurrentCount++;
        }
    }

    public class CounterState
    {
        public int CurrentCount { get; set; }
    }
}

Lorsque le composant s'exécute, CurrentCount n'est défini qu'une seule fois pendant le prérendu. La valeur est restaurée lors du nouveau rendu du composant. Voici un exemple de sortie.

Remarque

Si l'application adopte le routage interactif et que la page est atteinte via une navigation interne améliorée , le prérendering ne se produit pas. Par conséquent, vous devez effectuer un rechargement de page complet pour que le composant affiche la sortie suivante. Pour plus d'informations, voir la section Routage interactif et pré-rendu.

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

Dans l’exemple suivant qui sérialise l’état pour plusieurs composants du même type :

  • Les propriétés annotées avec l’attribut [SupplyParameterFromPersistentComponentState] sont sérialisées et désérialisées pendant le prérendering.
  • L’attribut@key de directive est utilisé pour vérifier que l’état est correctement associé à l’instance de composant.
  • La Element propriété est initialisée dans la méthode duOnInitialized cycle de vie pour éviter les exceptions de références nulles, de la même façon que les références nulles sont évitées dans le cas des paramètres de requête et des données de formulaire.

PersistentChild.razor :

<div>
    <p>Current count: @Element.CurrentCount</p>
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</div>

@code {
    [SupplyParameterFromPersistentComponentState]
    public State Element { get; set; }

    protected override void OnInitialized()
    {
        Element ??= new State();
    }

    private void IncrementCount()
    {
        Element.CurrentCount++;
    }

    private class State
    {
        public int CurrentCount { get; set; }
    }
}

Parent.razor :

@page "/parent"

@foreach (var element in elements)
{
    <PersistentChild @key="element.Name" />
}

Dans l’exemple suivant qui sérialise l’état d’un service d’injection de dépendances :

  • Les propriétés annotées avec l’attribut [SupplyParameterFromPersistentComponentState] sont sérialisées pendant le prérendering et désérialisées lorsque l’application devient interactive.
  • La méthode AddPersistentService est utilisée pour enregistrer le service en vue de la persistance. Le mode de rendu est requis, car le mode de rendu ne peut pas être déduit du type de service. Utilisez l’une des valeurs suivantes :
    • RenderMode.Server: le service est disponible pour le mode de rendu interactive du serveur.
    • RenderMode.Webassembly: Le service est disponible pour le mode de rendu WebAssembly interactif.
    • RenderMode.InteractiveAuto: le service est disponible pour les modes de rendu Interactive Server et Interactive Webassembly si un composant s’affiche dans l’un de ces modes.
  • Le service est résolu pendant l’initialisation d’un mode de rendu interactif, et les propriétés annotées avec l’attribut [SupplyParameterFromPersistentComponentState] sont désérialisées.

Remarque

Seuls les services à portée persistants sont pris en charge.

CounterService.cs :

public class CounterService
{
    [SupplyParameterFromPersistentComponentState]
    public int CurrentCount { get; set; }

    public void IncrementCount()
    {
        CurrentCount++;
    }
}

Dans Program.cs :

builder.Services.AddPersistentService<CounterService>(RenderMode.InteractiveAuto);

Les propriétés sérialisées sont identifiées à partir de l’instance de service réelle :

  • Cette approche permet de marquer une abstraction en tant que service persistant.
  • Permet aux implémentations réelles d’être des types internes ou différents.
  • Prend en charge le code partagé dans différents assemblies.
  • Résulte en la révélation des mêmes propriétés dans chaque instance.

En guise d’alternative à l’utilisation du modèle déclaratif pour conserver l’état avec l’attribut [SupplyParameterFromPersistentComponentState] , vous pouvez utiliser le PersistentComponentState service directement, ce qui offre une plus grande flexibilité pour les scénarios de persistance d’état complexes. Appelez PersistentComponentState.RegisterOnPersisting pour enregistrer un rappel afin de conserver l’état du composant lors du prérendu. L’état est récupéré lorsque le composant s’affiche de manière interactive. Effectuez l'appel à la fin du code d'initialisation afin d'éviter une condition de concurrence potentielle lors de l'arrêt de l'application.

L'exemple de composant de compteur suivant persiste l'état du compteur pendant le prérendu et récupère l'état pour initialiser le composant.

PrerenderedCounter3.razor :

@page "/prerendered-counter-3"
@implements IDisposable
@inject ILogger<PrerenderedCounter3> Logger
@inject PersistentComponentState ApplicationState

<PageTitle>Prerendered Counter 3</PageTitle>

<h1>Prerendered Counter 3</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()
    {
        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);
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistCount);
    }

    private Task PersistCount()
    {
        ApplicationState.PersistAsJson(nameof(currentCount), currentCount);

        return Task.CompletedTask;
    }

    private void IncrementCount() => currentCount++;

    void IDisposable.Dispose() => persistingSubscription.Dispose();
}

Lorsque le composant s'exécute, currentCount n'est défini qu'une seule fois pendant le prérendu. La valeur est restaurée lors du nouveau rendu du composant. Voici un exemple de sortie.

Remarque

Si l'application adopte le routage interactif et que la page est atteinte via une navigation interne améliorée , le prérendering ne se produit pas. Par conséquent, vous devez effectuer un rechargement de page complet pour que le composant affiche la sortie suivante. Pour plus d'informations, voir la section Routage interactif et pré-rendu.

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

Pour préserver l'état prérendu, décidez de l'état à persister en utilisant le service PersistentComponentState. PersistentComponentState.RegisterOnPersisting inscrit un rappel pour conserver l’état du composant lors de la préversion. L’état est récupéré lorsque le composant s’affiche de manière interactive. Effectuez l'appel à la fin du code d'initialisation afin d'éviter une condition de concurrence potentielle lors de l'arrêt de l'application.

L'exemple de composant de compteur suivant persiste l'état du compteur pendant le prérendu et 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()
    {
        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);
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistCount);
    }

    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 qu'une seule fois pendant le prérendu. La valeur est restaurée lors du nouveau rendu du composant. Voici un exemple de sortie.

Remarque

Si l'application adopte le routage interactif et que la page est atteinte via une navigation interne améliorée , le prérendering ne se produit pas. Par conséquent, vous devez effectuer un rechargement de page complet pour que le composant affiche la sortie suivante. Pour plus d'informations, voir la section Routage interactif et pré-rendu.

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.

L’état préréenderé persistant est transféré au client, où il est utilisé pour restaurer l’état du composant. Pendant le rendu côté client (CSR), InteractiveWebAssemblyles données sont exposées au navigateur et ne doivent pas contenir d’informations sensibles et privées. Pendant le rendu interactif côté serveur (SSR interactif), InteractiveServerASP.NET Core Data Protection garantit que les données sont transférées en toute sécurité. Le mode de rendu InteractiveAuto combine WebAssembly et l'interactivité du serveur, il est donc nécessaire de prendre en compte l'exposition des données au navigateur, comme dans le cas du CSR.

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

Pour les composants intégrés dans une page ou une vue d'une application Razor Pages ou MVC, vous devez ajouter le Persist Component State Tag Helper avec la balise HTML <persist-component-state /> à l'intérieur de la balise de fermeture </body> de la mise en page de l'application. Cela n’est nécessaire que pour les applications Razor Pages et MVC. Pour plus d'informations, consultez Persist Component State Tag Helper dans ASP.NET Core.

Pages/Shared/_Layout.cshtml :

<body>
    ...

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

Routage interactif et prérendu

Lorsque le composant Routes ne définit pas de mode de rendu, l’application utilise l’interactivité et la navigation par page/composant. En utilisant la navigation par page/composant, la navigation interne† est gérée par le routage amélioré après que l'application est devenue interactive. †Interne dans ce contexte signifie que la destination URL de l'événement de navigation est un point de terminaison Blazor à l'intérieur de l'application.

Le service PersistentComponentState fonctionne uniquement sur le chargement initial de la page et non sur les événements de navigation de page améliorés internes.

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.

Si un circuit interactif a déjà été établi et qu’une navigation améliorée est effectuée sur une page utilisant l’état du composant persistant, l’état n’est pas disponible dans le circuit existant pour que le composant utilise. Il n'y a pas de prérendu pour la requête de page interne, et le service PersistentComponentState n'est pas au courant qu'une navigation améliorée s'est produite. Il n’existe aucun mécanisme permettant de fournir des mises à jour d’état aux composants qui s’exécutent déjà sur un circuit existant. La raison en est que Blazor prend uniquement en charge le passage de l’état du serveur au client au moment de l’initialisation du runtime, et non après le démarrage du runtime.

Des travaux supplémentaires sur le framework de Blazor pour résoudre ce scénario sont pris en considération pour .NET 10 (novembre 2025). Pour plus d'informations et une discussion de la communauté sur les solutions de contournement non prises en charge‡, voir Support persistent component state across enhanced page navigations ( dotnet/aspnetcore51584). Les solutions de contournement non prises en charge ne sont pas approuvées par Microsoft pour une utilisation dans les applications Blazor. Utiliser des packages, des approches et du code tiers à vos propres risques.

La désactivation de la navigation améliorée, qui réduit les performances mais évite également le problème du chargement de l'état avec PersistentComponentState pour les requêtes de pages internes, est couverte dans ASP.NET Core Blazor routing and navigation.

Guide de prérendu

Les conseils en matière de prérendu sont organisés dans la documentation Blazor par sujet. Les liens suivants couvrent toutes les orientations sur le prérendu dans l'ensemble de la documentation par sujet :

Pour .NET 7 ou versions antérieures, consultez Blazor WebAssembly les scénarios supplémentaires de sécurité : Prérendering avec l’authentification. Après avoir consulté le contenu de cette section, réinitialisez la liste déroulante du sélecteur de version de l’article de documentation sur la dernière version de .NET pour vous assurer que les pages de documentation se chargent pour la dernière version lors des visites ultérieures.