Bibliothèques Razor (RCL) et chargement différé
Une bibliothèque de classes Razor (RCL, Razor Class Library) peut apporter des pages routables ([Route]) à l'application cliente. Lagoon utilise son propre routeur : les pages d'une RCL ne sont pas trouvées tant que son assembly n'est pas déclarée au routeur. Deux modes sont possibles :
| Mode | Téléchargement de l'assembly | Déclaration |
|---|---|---|
| Au démarrage | avec le reste de l'application | GetRouterAdditionalAssemblies() |
| Différé (lazy loading) | à la première navigation vers une de ses pages | app.LazyAssemblies (OnConfigureBehavior) ou OnNavigateAsync |
Charger une RCL au démarrage
Le projet Client référence la RCL ; la méthode GetRouterAdditionalAssemblies de Main.cs ajoute son assembly au routeur.
protected override IEnumerable<Assembly> GetRouterAdditionalAssemblies()
{
yield return typeof(MyCompany.Orders.Pages.OrderList).Assembly;
}
Charger une RCL en différé
Le chargement différé réduit le volume téléchargé au démarrage : l'assembly de la RCL n'est récupérée qu'à la première navigation vers une de ses routes, puis gardée en mémoire.
1. Marquer l'assembly comme différée
Le projet Client référence la RCL et la déclare avec l'élément BlazorWebAssemblyLazyLoad :
<ItemGroup>
<ProjectReference Include="..\Orders\MyCompany.Orders.csproj" />
</ItemGroup>
<ItemGroup>
<BlazorWebAssemblyLazyLoad Include="MyCompany.Orders.wasm" />
</ItemGroup>
.wasmDepuis .NET 8, les assemblies sont publiées au format Webcil : le nom à déclarer, et à passer à Lagoon, se termine par .wasm (et non .dll). Seul un projet qui désactive Webcil (<WasmEnableWebcil>false</WasmEnableWebcil>) utilise l'extension .dll.
2. Associer un préfixe de route à l'assembly
Dans OnConfigureBehavior, app.LazyAssemblies.Add associe un préfixe de route aux assemblies à charger avant d'afficher une page de ce préfixe :
protected override void OnConfigureBehavior(ApplicationBehavior app)
{
// Toutes les routes "orders" et "orders/..." sont dans MyCompany.Orders
app.LazyAssemblies.Add("orders", "MyCompany.Orders.wasm");
}
Règles de correspondance du préfixe :
- la comparaison porte sur des segments entiers :
orderscorrespond àordersetorders/list, mais pas àorders2; - elle est insensible à la casse ;
- le préfixe ne contient pas de paramètre de route (
{id}) : seuls les premiers segments littéraux comptent ; - un préfixe peut demander plusieurs assemblies :
app.LazyAssemblies.Add("orders", "MyCompany.Orders.wasm", "MyCompany.Common.wasm").
Ce mode suffit dans la plupart des cas. Lagoon se charge du téléchargement, du dédoublonnage (une assembly n'est téléchargée qu'une fois, même si plusieurs navigations la demandent en même temps) et du rafraîchissement de la table de routes.
3. Cas avancés : OnNavigateAsync
Pour une logique que les préfixes ne couvrent pas, surchargez OnNavigateAsync dans Main.cs. Lagoon l'appelle avant chaque navigation, avant de chercher la page cible, après avoir déjà appliqué les règles de LazyAssemblies. Elle est aussi appelée avant l'ouverture de l'onglet par défaut d'une application à onglets et par WindowManager.OpenModalAsync, avec un jeton qui n'est jamais annulé.
Chaque navigation attend la fin de OnNavigateAsync : gardez-y un traitement rapide, sans appel au serveur.
protected override Task OnNavigateAsync(LgNavigationContext context)
{
if (context.StartsWithRoute("reports") && !context.Path.EndsWith("/print"))
{
context.LoadAssemblies("MyCompany.Reports.wasm");
}
return Task.CompletedTask;
}
Le contexte LgNavigationContext expose :
| Membre | Rôle |
|---|---|
Path | Chemin cible relatif à l'adresse de base de l'application, sans / au début ni à la fin, sans query string ni fragment (ex. orders/list). |
CancellationToken | Annulé quand une autre navigation remplace celle-ci. |
StartsWithRoute(string routePrefix) | Indique si le chemin commence par le préfixe (mêmes règles que LazyAssemblies). |
LoadAssemblies(params string[] assemblyFileNames) | Demande le téléchargement d'assemblies déclarées avec BlazorWebAssemblyLazyLoad. |
AddAssemblies(params Assembly[] assemblies) | Ajoute au routeur des assemblies déjà chargées par l'application elle-même. |
Si l'utilisateur navigue ailleurs pendant un téléchargement, la première navigation est abandonnée : seule la dernière est affichée. Le téléchargement en cours continue et son résultat sert à la navigation suivante.
Précharger une assembly
LoadLazyAssembliesAsync télécharge des assemblies et ajoute leurs pages au routeur sans navigation. Il sert par exemple à précharger un module en arrière-plan après l'affichage de l'accueil :
await App.LoadLazyAssembliesAsync(new[] { "MyCompany.Orders.wasm" });
Ouvrir une page différée dans une modale
WindowManager.OpenModal est synchrone et ne télécharge rien : la page doit déjà être routable. Utilisez WindowManager.OpenModalAsync, qui charge d'abord les assemblies de la route (règles LazyAssemblies et OnNavigateAsync) :
await App.WindowManager.OpenModalAsync("orders/detail/12", "Commande 12");
Onglets restaurés
En mode onglets, un onglet restauré au démarrage (TabSavingMethod) ou déclaré dans les onglets de démarrage peut pointer vers une page différée. Son assembly n'est pas téléchargée au démarrage : elle l'est à la première activation de l'onglet.
Navigation initiale
Quand l'application démarre directement sur une page différée (lien direct, rechargement de la page), l'écran de démarrage reste affiché pendant le téléchargement de l'assembly.
Erreurs
Si une assembly ne peut pas être téléchargée (réseau, nom absent des éléments BlazorWebAssemblyLazyLoad), un message d'erreur invite à recharger la page et la page « introuvable » remplace la page demandée. Pendant la navigation initiale, le message s'affiche dès que l'application est affichée.
Le runtime WebAssembly mémorise l'échec d'un téléchargement : les navigations suivantes échouent aussi, jusqu'au rechargement de la page.
Les routes de l'assembly s'ajoutent à celles de l'application :
- une route identique à une route existante est ignorée : la page déjà déclarée reste affichée ;
- des routes ambiguës (par exemple
orders/{id}dans la RCL etorders/{name}dans l'application) font échouer le chargement, avec un message d'erreur ; les autres assemblies différées restent utilisables.
Une assembly que l'application a déjà chargée elle-même s'ajoute au routeur avec AddAssemblies, et non avec LoadAssemblies.
Limites
- Pas de services DI dans la RCL différée. Le conteneur de services est construit au démarrage : les services utilisés par les pages différées doivent être enregistrés dans une assembly chargée au démarrage (le projet
Client, ou une bibliothèque partagée non différée). - RCL simple uniquement. La RCL différée ne doit pas être un module Lagoon (
Lagoon.*) : les modules Lagoon qui exposent des pages sont chargés au démarrage. LeDico.xmlplacé à la racine d'une RCL référencée en projet (ProjectReference) est fusionné au build dans le dictionnaire de l'application, que la RCL soit différée ou non ; ses icônes et ses styles SCSS ne passent pas par le pipeline de ressources Lagoon. - Pas de référence de type depuis l'assembly principale. Une référence à un type de la RCL dans le code du
Client(par exemple l'appel deOrderList.Link()pour construire le menu) échoue tant que l'assembly n'est pas chargée : le runtime ne télécharge pas une assembly différée de lui-même. Construisez les liens à partir de la route sous forme de texte :LgPageLink.Create("orders/list", "#menuOrders", IconNames.All.Window). - Ce n'est pas une mesure de sécurité. Une assembly différée reste téléchargeable par n'importe quel client : les pages gardent leurs attributs
[Authorize]et les autorisations restent contrôlées côté serveur.
Voir aussi
- Onglets : sauvegarde et restauration des onglets ouverts.
- Configuration côté client : vue d'ensemble de
OnConfigureBehavior.