Bibliothèques de classes Razor (RCL) ASP.NET Core avec rendu côté serveur statique (SSR statique)

Cet article fournit des conseils aux auteurs de bibliothèques de composants qui envisagent de prendre en charge le rendu côté serveur statique (SSR statique).

Blazor encourage le développement d’un écosystème de bibliothèques de composants open source et commerciales, officiellement appelées bibliothèques de classes Razor (RCL). Les développeurs peuvent également créer des composants réutilisables pour les partager en privé entre les applications de leur propre entreprise. Dans l’idéal, les composants sont développés pour être compatibles avec autant de modèles d’hébergement et de modes de rendu que possible. Le SSR statique introduit des restrictions supplémentaires qui peuvent être plus difficiles à prendre en charge que les modes de rendu interactifs.

Comprendre les fonctionnalités et les restrictions du SSR statique

Le SSR statique est un mode dans lequel les composants s’exécutent lorsque le serveur gère une requête HTTP entrante. Blazor restitue le composant au format HTML, qui est inclus dans la réponse. Une fois la réponse envoyée, le composant côté serveur et l’état du renderer sont abandonnés, ne laissant dans le navigateur que le code HTML.

L’avantage de ce mode est un hébergement plus économique et plus évolutif, car aucune ressource de serveur continue n’est requise pour contenir l’état du composant, aucune connexion continue ne doit être conservée entre le navigateur et le serveur, et aucune charge utile WebAssembly n’est requise dans le navigateur.

Par défaut, tous les composants existants peuvent toujours être utilisés avec le SSR statique. Toutefois, le prix à payer de ce mode est que les gestionnaires d’événements, tels que @onclick†, ne peuvent pas être exécutés pour les raisons suivantes :

  • Il n’y a aucun code .NET dans le navigateur pour les exécuter.
  • Le serveur abandonne immédiatement tous les composants et tous les états du renderer qui seraient nécessaires pour exécuter des gestionnaires d’événements ou pour re-restituer les mêmes instances de composant.

†Exception faite du gestionnaire d’événements @onsubmit pour les formulaires, qui reste fonctionnel, quel que soit le mode de rendu.

Cela équivaut à la façon dont les composants se comportent pendant le prérendu, avant le démarrage d’un circuit Blazor ou d’un runtime Blazor WebAssembly.

Pour les composants dont le seul rôle consiste à produire du contenu DOM en lecture seule, ces comportements pour le SSR statique sont tout à fait suffisants. Toutefois, les auteurs de bibliothèques doivent réfléchir à l’approche à adopter lorsqu’ils incluent des composants interactifs dans leurs bibliothèques.

Options pour les auteurs de composants

Les trois (3) principales approches sont les suivantes :

  • Ne pas utiliser les comportements interactifs (de base)

    Pour les composants dont le seul rôle consiste à produire du contenu DOM en lecture seule, le développeur n’est pas tenu de prendre des mesures spéciales. Ces composants fonctionnent naturellement avec n’importe quel mode de rendu.

    Exemples :

    • Un composant « carte utilisateur » qui charge les données correspondant à une personne et les restitue dans une interface utilisateur stylée avec une photo, un nom de poste et autres détails.
    • Un composant « vidéo » qui fait office d’enveloppe pour l’élément HTML <video>, ce qui le rend plus pratique à utiliser dans un composant Razor.
  • Exiger un rendu interactif (de base)

    Vous pouvez choisir d’exiger que votre composant soit utilisé uniquement avec le rendu interactif. Cela limite l’applicabilité de votre composant, mais cela signifie que vous pouvez librement vous appuyer sur des gestionnaires d’événements arbitraires. Même après, vous devriez toujours éviter de déclarer un @rendermode spécifique et autoriser l’auteur de l’application qui consomme votre bibliothèque à en sélectionner un.

    Exemples :

    • Composant de montage vidéo où les utilisateurs peuvent coller et réorganiser les séquences vidéo. Même s’il y avait un moyen de représenter ces opérations de montage avec des boutons HTML simples et des posts de formulaire, l’expérience utilisateur ne serait pas viable sans une vraie interactivité.
    • Un éditeur de documents collaboratif qui doit afficher les activités des autres utilisateurs en temps réel.
  • Utiliser des comportements interactifs, mais concevoir pour le SSR statique et une amélioration progressive (Avancé)

    De nombreux comportements interactifs peuvent être implémentés à l’aide de fonctionnalités HTML uniquement. Avec une bonne compréhension du code HTML et CSS, vous pouvez souvent produire une base de référence utile qui fonctionne avec le SSR statique. Vous pouvez toujours déclarer des gestionnaires d’événements qui implémentent des comportements facultatifs plus avancés, lesquels fonctionnent uniquement dans les modes de rendu interactifs.

    Exemples :

    • Un composant de grille. Sous le SSR statique, le composant peut uniquement prendre en charge l’affichage des données et la navigation entre les pages (implémentées avec des liens <a>). Lorsqu’il est utilisé avec un rendu interactif, le composant peut ajouter un tri et un filtrage dynamiques.
    • Un composant d’ensemble de tabulations. Tant que la navigation entre les onglets se fait en utilisant des liens <a> et que l’état est conservé uniquement dans les paramètres de requête de l’URL, le composant peut fonctionner sans @onclick.
    • Un composant de chargement de fichier avancé. Sous le SSR statique, le composant peut se comporter en tant que <input type=file> natif. Lorsqu’il est utilisé avec le rendu interactif, le composant peut également afficher la progression du chargement.
    • Un composant de cotations boursières. Sous le SSR statique, le composant peut afficher les cotations boursières lors du rendu du code HTML. Lorsqu’il est utilisé avec un rendu interactif, le composant peut ensuite mettre à jour le cours des actions en temps réel.

Pour l’une de ces stratégies, il existe également la possibilité d’implémenter des fonctionnalités interactives avec JavaScript.

Pour choisir parmi ces approches, les auteurs de composants Razor réutilisables doivent faire un compromis entre le coût et les avantages. Votre composant est plus utile et dispose d’une base d’utilisateurs potentielle plus large s’il prend en charge tous les modes de rendu, y compris le SSR statique. Toutefois, concevoir et implémenter un composant qui prend en charge et tire le meilleur parti de chaque mode de rendu demande plus de travail.

Quand utiliser la directive @rendermode

Dans la plupart des cas, les auteurs de composants réutilisables n’ont pas intérêt à spécifier de mode de rendu, même lorsque l’interactivité est requise. C’est parce que l’auteur du composant ne sait pas si l’application active la prise en charge pour InteractiveServer, InteractiveWebAssembly ou pour les deux avec InteractiveAuto. En ne spécifiant aucun @rendermode, l’auteur du composant laisse le choix au développeur de l’application.

Même si l’auteur du composant pense qu’une interactivité est requise, il peut toujours y avoir des cas où un auteur d’application considère qu’il suffit d’utiliser le SSR statique seul. Par exemple, un composant de carte avec une interactivité glisser-zoomer peut sembler nécessiter une interactivité. Toutefois, certains scénarios peuvent uniquement appeler le rendu d’une image de carte statique et éviter les fonctionnalités de déplacement/zoom.

La seule raison pour laquelle un auteur de composant réutilisable aurait intérêt à utiliser la directive @rendermode sur son composant est si l’implémentation est fondamentalement couplée à un mode de rendu spécifique. Cela provoquerait certainement une erreur si elle était utilisée dans un autre mode. Imaginez un composant ayant pour objectif principal d’interagir directement avec le système d’exploitation hôte à l’aide d’API spécifiques à Windows ou Linux. Il est probablement impossible d’utiliser un tel composant sur WebAssembly. Dans ce cas, il est raisonnable de déclarer @rendermode InteractiveServer pour le composant.

Rendu en streaming

Les composants réutilisables Razor sont libres de déclarer @attribute [StreamRendering] pour le rendu en streaming ([StreamRendering] attribut API). Cela entraîne des mises à jour incrémentielles de l’interface utilisateur pendant le SSR statique. Étant donné que les mêmes modèles de chargement de données produisent des mises à jour incrémentielles de l'interface utilisateur lors du rendu interactif, quelle que soit la présence de l'attribut [StreamRendering], le composant peut se comporter correctement dans tous les cas. Même dans les cas où le SSR statique en streaming est supprimé sur le serveur, le composant restitue toujours son état final correctement.

Les composants Razor réutilisables peuvent utiliser des liens et une navigation améliorée. Les balises HTML <a> devraient produire des comportements équivalents avec ou sans composant Router interactif et indiquer si la navigation améliorée est activée/désactivée au niveau ancêtre du DOM.

Utilisation de formulaires dans les modes de rendu

Les composants Razor réutilisables peuvent inclure des formulaires (<form> ou <EditForm>), car ceux-ci peuvent être implémentés pour fonctionner de la même manière dans les modes de rendu statiques et interactifs.

Prenons l’exemple suivant :

<EditForm Enhance FormName="NewProduct" Model="Model" OnValidSubmit="SaveProduct">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <p>Name: <InputText @bind-Value="Item.Name" /></p>

    <button type="submit">Submit</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    public Product? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private async Task Save()
    {
        ...
    }
}

Les API Enhance, FormName et SupplyParameterFromFormAttribute sont utilisées uniquement pendant le SSR statique et sont ignorées pendant le rendu interactif. Le formulaire fonctionne correctement pendant le SSR interactif et statique.

Éviter les API propres au SSR statique

Pour rendre un composant réutilisable qui fonctionne sur tous les modes de rendu, ne comptez pas sur HttpContext parce qu’il est seulement disponible pendant le SSR statique. L’utilisation de l’API HttpContext ne présente aucun intérêt pendant le rendu interactif, car il n’y a pas de requête HTTP active en cours à ce moment-là. Il est inutile de penser à définir un code d’état ou à écrire quelque chose dans la réponse.

Les composants réutilisables sont libres de recevoir un HttpContext s’il est disponible, comme suit :

[CascadingParameter]
public HttpContext? Context { get; set; }

La valeur est null pendant le rendu interactif et est définie uniquement pendant le SSR statique.

Dans de nombreux cas, il existe de meilleures alternatives que d’utiliser HttpContext. Si vous avez besoin de connaître l’URL actuelle ou d’effectuer une redirection, les API sur NavigationManager fonctionnent avec tous les modes de rendu. Si vous avez besoin de connaître l’état d’authentification de l’utilisateur, faites appel au service AuthenticationStateProvider de Blazor plutôt qu’au service HttpContext.User.