Découvrez comment fonctionne le prérendu dans Blazor Server et pourquoi la désactivation du prérendu n’est pas la meilleure option.
Quand j’ai rencontré pour la première fois prérenduJ’ai fait beaucoup d’erreurs. Je n’ai pas compris comment fonctionnait le prérendu dans Blazor Server. J’ai choisi par défaut désactiver le prérendu et l’a complètement ignoré.
Avec plus d’expérience, j’ai appris que le prérendu dans Blazor Server est utile pour offrir une meilleure expérience utilisateur. Un autre avantage de l’utilisation du prérendu est qu’il peut affecter optimisation des moteurs de recherche (SEO) de manière positive car les performances du premier rendu vont augmenter.
Dans cet article, je vais vous expliquer tout ce que vous devez savoir sur le prérendu dans Blazor Server pour vous aider à en tirer le meilleur parti et éviter de commettre la même erreur que moi.
Rendu de serveur statique (SSR) et rendu de flux
À partir de .NET 8, rendu du serveur statique (SSR) et rendu du flux sont la valeur par défaut. Si nous ne précisons pas Serveur Blazor ou Blazor WebAssembly en tant que mode d’interactivité, Blazor fonctionnera en mode SSR.
Le rendu de flux est une option supplémentaire pour SSR et permet l’envoi de données du serveur au client lorsqu’elles arrivent dans la même requête.
SSR et le rendu de flux n’ont rien à voir avec Blazor Server ou le prérendu dans Blazor Server. Il est essentiel de faire la distinction.
Un exemple de page typique
Pour cet exemple, j’utiliserai un simple composant de page Blazor qui effectue une tâche typique. Il charge les données d’un service (qui pourrait les charger à partir d’une base de données) et les restitue à l’écran.
Je utilise l statistiques de tous les temps sur les joueurs de la Ligue nationale de hockey (LNH) et afficher le nom du joueur, le nombre de matchs joués et le nombre de points marqués.
@page "https://www.telerik.com/"
@inject IStatsService StatsService;
@using BlazorServerPrerendering.Services
<PageTitle>NHL All Time Most Points Scored</PageTitle>
<h1>NHL All Time Most Points Scored</h1>
<table>
<thead>
<tr>
<th style="width: 180px;">Name</th>
<th style="width: 140px;">Games Played</th>
<th style="width: 140px;">Points Scored</th>
</tr>
</thead>
<tbody>
@foreach (var player in Players)
{
<tr>
<td>@player.Name</td>
<td>@player.GamesPlayed</td>
<td>@player.Points</td>
</tr>
}
</tbody>
</table>
@code {
public IEnumerable<Player> Players { get; set; } = new List<Player>();
protected async override Task OnInitializedAsync()
{
Players = await StatsService.GetMostCareerPoints();
}
}
Le StatsService
la mise en œuvre ressemble à ceci :
namespace BlazorServerPrerendering.Services;
public class StatsService : IStatsService
{
public async Task<IEnumerable<Player>> GetMostCareerPoints()
{
await Task.Delay(2500);
return new List<Player>
{
new Player("Wayne Gretzky", 1487, 2857),
new Player("Jaromir Jagr", 1733, 1921),
new Player("Mark Messier", 1756, 1887),
new Player("Gordie Hower", 1767, 1850),
new Player("Ron Francis", 1731, 1798),
new Player("Marcel Dionne", 1348, 1771),
new Player("Steve Yzerman", 1514, 1755),
new Player("Mario Lemieux", 915, 1723),
new Player("Joe Sakic", 1378, 1641),
new Player("Sidney Crosby", 1272, 1596)
};
}
}
Tu peux accéder au code utilisé dans cet exemple sur GitHub.
Serveur Blazor avec prérendu désactivé
Tout d’abord, discutons du comportement d’un composant de page Blazor Server avec prérendu désactivé.
Pour rappel rapide, vous pouvez désactiver le prérendu pour l’interactivité de Blazor Server globalement lorsque vous utilisez le dernier modèle de projet .NET 8 Blazor Web App dans le App.razor
déposer:
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
Vous pouvez également désactiver le prérendu sur un par composant base.
Lorsque je démarre l’exemple d’application, j’obtiens la réponse HTML suivante à la demande de page :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<base href="/">
<link rel="stylesheet" href="bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="app.css">
<link rel="stylesheet" href="BlazorServerPrerendering.styles.css">
<link rel="icon" type="image/png" href="favicon.png">
</head>
<body>
<script src="_framework/blazor.web.js"></script>
<script type="text/javascript" src="/_vs/browserLink" async="async" id="__browserLink_initializationData" data-requestId="87d1b4f53dcb49c2bbceff7bcec1a36b" data-requestMappingFromServer="false" data-connectUrl="http://localhost:51174/dc88d2a6c0df4143a162fcf28535f3bb/browserLink"></script>
<script src="/_framework/aspnetcore-browser-refresh.js"></script>
</body>
</html>
Comme vous pouvez le constater, nous obtenons le head
section et la script
sable stylesheet
les références. Cependant, nous ne voyons aucun contenu dans le HTML body
section.
Inspectons maintenant les messages envoyés via le SignalR connexion. Il y a beaucoup de messages échangés, mais quand on cherche les messages les plus longs, on voit un message avec 3,5 Ko en taille.
Quand je regarde les données transmises, je peux repérer le « Parties jouées » et « Points marqués » texte. Cela signifie que la structure de la page est envoyée via la connexion SignalR.
Quelques messages plus tard, nous voyons un autre message intéressant d’une longueur de 3,0 Ko. En explorant son contenu, on voit que le contenu de la table avec les statistiques des joueurs est envoyé dans ce message.
En conclusion: Lorsque le prérendu est désactivé, seuls les éléments essentiels sont transmis dans le cadre de la réponse HTTP. L’ensemble du contenu de la page est divisé en deux messages SignalR. Cela signifie que tant que la connexion SignalR n’est pas établie, l’utilisateur ne verra aucun contenu à l’écran.
Serveur Blazor avec prérendu activé
Maintenant, allons activer le prérendu pour ce composant de page et inspectez la différence de comportement.
Nous changeons le code dans le App.razor
composant pour permettre le prérendu à l’échelle mondiale.
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: true)" />
<Routes @rendermode="new InteractiveServerRenderMode(prerender: true)" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<base href="/">
<link rel="stylesheet" href="bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="app.css">
<link rel="stylesheet" href="BlazorServerPrerendering.styles.css">
<link rel="icon" type="image/png" href="favicon.png">
<title>NHL All Time Most Points Scored</title>
</head>
<body>
<div class="page" b-afgyb8e6cv>
<div class="sidebar" b-afgyb8e6cv>
</div>
<main b-afgyb8e6cv>
<article class="content px-4" b-afgyb8e6cv>
<h1>NHL All Time Most Points Scored</h1>
<table>
<thead>
<tr>
<th style="width: 180px;">Name</th>
<th style="width: 140px;">Games Played</th>
<th style="width: 140px;">Points Scored</th>
</tr>
</thead>
<tbody></tbody>
</table>
</article>
</main>
</div>
<div id="blazor-error-ui" b-afgyb8e6cv>
An unhandled error has occurred.
<a href class="reload" b-afgyb8e6cv>Reload</a>
<a class="dismiss" b-afgyb8e6cv>🗙</a>
</div>
<script src="_framework/blazor.web.js"></script>
<script type="text/javascript" src="/_vs/browserLink" async="async" id="__browserLink_initializationData" data-requestId="e703734d73c14a95b38326c1c380c3e4" data-requestMappingFromServer="false" data-connectUrl="http://localhost:51174/dc88d2a6c0df4143a162fcf28535f3bb/browserLink"></script>
<script src="/_framework/aspnetcore-browser-refresh.js"></script>
</body>
</html>
Comme vous pouvez le constater, cette fois, nous obtenons beaucoup plus d’informations dans le body
section de la réponse HTML à la demande de page initiale. Nous obtenons le table
définition incluant les en-têtes du tableau.
Remarquez le Commentaires d’espace réservé Blazordont un prerenderId
indiquant que cette partie de la page sera remplacée une fois le chargement complet de la page terminé.
Indice: Pour plus de clarté, j’ai omis certains des GUID utilisés. Vous pouvez explorer la réponse HTTP complète lorsque vous exécutez vous-même l’exemple d’application.
Voyons maintenant comment les statistiques des joueurs sont transférées du serveur vers le client.
Encore une fois, nous ouvrons le outils de développement pour inspecter les messages envoyés via la connexion SignalR. Semblable au prérendu désactivé, les données du joueur sont transmises via un message SignalR.
Cette partie reste la même puisque, avec l’interactivité de Blazor Server, nous exploitons une connexion SignalR pour communiquer avec le client.
Avantages du prérendu dans Blazor Server
Avec prérenduBlazor Server envoie une page HTML rendue du serveur au client sans activer les gestionnaires d’événements.
Du côté positif, le serveur envoie l’interface utilisateur HTML sous la forme partie de la réponse HTTP initiale à l’utilisateur le plus rapidement possible. L’expérience utilisateur est améliorée car l’application Web semble plus réactive.
Le prérendu peut également améliorer le référencement car les robots d’exploration peuvent calculer leur classement de vitesse en fonction de la réponse initiale. Avec le prérendu désactivé, un robot d’exploration n’est pas en mesure de voir la structure d’une page car il n’établit pas de connexion SignalR.
En revanche, une fois la page entièrement chargée, Blazor Server envoie une mise à jour via son Connexion SignalR, et certaines parties de l’interface utilisateur sont remplacées par du nouveau contenu. Après cette étape, les gestionnaires d’événements sont activés et l’application réagit aux entrées de l’utilisateur, comme appuyer sur un bouton.
Cela signifie également que jusqu’à ce que les gestionnaires d’événements soient activés, l’application ne réagit pas aux entrées de l’utilisateur, telles que les clics sur des boutons ou toute autre interactivité. Avec le prérendu, le client obtient une réponse HTML initiale même si la connexion SignalR n’a pas encore été établie.
Comme mentionné dans l’introduction de cet article, cela profite principalement aux la réactivité de l’application et, par conséquent, a un impact positif sur le classement des moteurs de recherche.
C’est particulièrement important pour les applications et les sites Web publics et peut être moins pertinent pour les applications internes. Cependant, les applications internes bénéficient également grandement d’une meilleure réactivité.
L’effet du prérendu devient de plus en plus mesurable à mesure que le laps de temps entre le rendu initial (prérendu) et l’établissement de la connexion SignalR augmente. Cela peut être le cas lorsque l’application est soumise à une forte charge ou que la latence entre le serveur et le client est élevée.
Le problème du prérendu : OnInitializedAsync est appelé deux fois
Il existe un problème bien connu lorsque l’on travaille avec le prérendu. Le OnInitializedAsync
la méthode du cycle de vie est appelée deux fois. La première fois que la page est pré-rendu sur le serveur, et la deuxième fois lorsque la page est rendue avec Interactivité du serveur Blazor à travers le Connexion SignalR.
La plupart des développeurs décident de désactiver le prérendu à cause de ce problème. Et je le comprends parfaitement. J’ai fait la même chose jusqu’à ce que je comprenne parfaitement le prérendu.
Maintenant que je vois le avantages du prérenduje dois encore trouver une solution à prévenir le service de être appelé deux fois. Je ne veux tout simplement pas charger les données de la base de données deux fois à chaque chargement de page.
Blazor fournit le PersistentComponentState
tapez pour gérer ce problème. Il existe d’autres stratégies de mise en cache, mais je me concentrerai sur celle mentionnée dans le Documentation Microsoft.
L’idée est que nous stocker l’état dès le premier appel de service et réutilisation lors du deuxième appel au lieu d’appeler le service une deuxième fois.
Voyons comment nous intégrons le PersistentComponentState
tapez sur notre page pour éviter que le service ne soit appelé deux fois.
@inject PersistentComponentState ApplicationState
@implements IDisposable
Dans le composant page, nous injectons une instance du PersistentComponentState
tapez et ajoutez le @implements
directive pour le IDisposable
taper.
private PersistingComponentStateSubscription _persistingSubscription;
Ensuite, nous ajoutons une nouvelle variable d’instance de type PersistingComponentStateSubscription
. Il nous fournit une interface pour stocker et charger l’état du composant Blazor.
protected async override Task OnInitializedAsync()
{
_persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
var statedLoaded = ApplicationState.TryTakeFromJson<IEnumerable<Player>>("players", out var players);
Players = statedLoaded && players != null ? players : await StatsService.GetMostCareerPoints();
}
Le OnInitializeAsync
la méthode est maintenant différente. Tout d’abord, nous utilisons la variable d’instance de type PersistingComponentStateSubscription
pour enregistrer le PersistData
méthode de rappel. La méthode sera déclenché par le framework Blazor lorsque le composant est rendu.
Ensuite, nous utilisons le ApplicationState
objet pour accéder à l’état stocké pour le players
clé. L’instruction return vérifie d’abord si un état a été chargé et si l’état ne l’est pas. null
. Si le chèque revient true
, nous renvoyons l’état de l’application chargée. Sinon, nous accédons à notre service et chargeons les données.
private Task PersistData()
{
ApplicationState.PersistAsJson("players", Players);
return Task.CompletedTask;
}
Le PersistData
la méthode utilise le ApplicationState
objet et conserve les données stockées dans la variable d’instance Players
. Encore une fois, cette méthode sera appelé par le framework Blazor lorsque le composant est rendu.
public void Dispose()
{
_persistingSubscription.Dispose();
}
Enfin et surtout, nous supprimons la méthode de rappel du PersistingComponentStateSubscription
lors de la suppression de l’instance du composant Blazor.
Il est important de supprimer le rappel. Sinon, vous vous retrouverez avec un fuite de mémoire puisque le rappel restera enregistré même si le composant lui-même a été récupéré.
Je sais que cette méthode nécessite actuellement beaucoup de code. J’aurais aimé que ce soit plus simple. Cependant, c’est le manière standard d’utiliser le prérendu dans Blazor Server et éviter les appels de service en double dans le OnInitializedAsync
méthode. Et une fois habitué au modèle, ce n’est pas si difficile à mettre en œuvre.
Soyez conscient de la navigation améliorée dans .NET 8
Avec .NET 8, Blazor a introduit navigation améliorée. Lorsqu’il est activé, le prérendu ne se produit pas pendant la navigation interne. Au lieu de cela, le contenu sera diffusé via la connexion SignalR (déjà ouverte).
Si vous souhaitez tester le comportement de prérendu d’une page Blazor Server, un chargement de page complet est requis.
Conclusion
Nous avons appris quoi prérendu dans Blazor Server est et comment en profiter pour améliorer l’expérience utilisateur et éventuellement l’optimisation des moteurs de recherche d’une application Web Blazor.
Nous avons appris les différences entre l’utilisation Interactivité du serveur Blazor avec le prérendu activé et désactivé.
Nous avons appris à mettre en œuvre correctement les appels de service à l’intérieur du OnInitializedAsync
méthode du cycle de vie pour éviter les appels de service en double en tirant parti de PersistentComponentState
et PersistingComponentStateSubscription
les types.
Tu peux accéder au code utilisé dans cet exemple sur GitHub.
Si vous souhaitez en savoir plus sur le développement de Blazor, vous pouvez regarder mon cours intensif Blazor gratuit sur YouTube. Et restez à l’écoute du blog Telerik pour en savoir plus Les bases du Blazor.
Source link