JavaScript isolé dans Blazor avec des fichiers JS colocalisés
Si vous avez déjà travaillé avec Blazor et JS Interop, vous vous êtes probablement retrouvé avec un énorme fichier app.js rempli de fonctions aléatoires pour différents composants. Cela fonctionne, mais ça devient vite compliqué. Heureusement, il existe une approche beaucoup plus propre : les fichiers JavaScript colocalisés.
L’idée
Tout comme l’isolation CSS, Blazor vous permet de placer un fichier .razor.js à côté de votre composant. Le module JavaScript est chargé à la demande, uniquement lorsque le composant en a réellement besoin. Pas de scripts globaux, pas de pollution.
Le configurer
Disons que nous avons un composant Clipboard.razor qui copie le texte dans le presse-papiers. Créez un fichier appelé Clipboard.razor.js juste à côté :
export function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
console.log("Copied to clipboard!");
});
}
Notez le mot-clé export — c’est important. Blazor le charge comme un module ES standard.
Chargement du module dans Blazor
Dans votre composant, vous utilisez IJSRuntime pour importer le module. Le chemin suit une convention : ./_content/{ASSEMBLY_NAME}/{COMPONENT_PATH}.razor.js pour les bibliothèques, ou simplement le chemin relatif du projet en cours.
@inject IJSRuntime JS
@implements IAsyncDisposable
<button @onclick="Copy">Copy to clipboard</button>
@code {
[Parameter]
public string Text { get; set; }
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>(
"import", "./Components/Clipboard.razor.js");
}
}
private async Task Copy()
{
if (module is not null)
{
await module.InvokeVoidAsync("copyToClipboard", Text);
}
}
public async ValueTask DisposeAsync()
{
if (module is not null)
{
await module.DisposeAsync();
}
}
}
Quelques points à noter ici :
- Nous chargeons le module dans
OnAfterRenderAsynccar JS Interop n’est pas disponible lors du prérendu côté serveur - On garde une référence au module avec
IJSObjectReference - Nous implémentons
IAsyncDisposablepour nettoyer le module lorsque le composant est détruit
Pourquoi c’est mieux
Avant, je mettais tout dans un seul wwwroot/js/app.js. Cela a fonctionné, mais trouver des fonctions était pénible, et chaque page chargeait du JavaScript dont elle n’avait pas besoin. Avec les fichiers JS colocalisés :
- Chaque composant possède son propre JavaScript
- Les modules sont chargés paresseusement, uniquement en cas de besoin
- Aucun conflit de nom de fonction global
- Plus facile à maintenir et à supprimer — lorsque vous supprimez le composant, vous supprimez le JS avec lui
Un piège avec le chemin
Le chemin que vous transmettez à import dépend si vous vous trouvez dans une application Blazor autonome ou dans une bibliothèque de classes Razor. Pour une application Blazor standard, le chemin est relatif à wwwroot. Le fichier .razor.js y est copié au moment de la construction, vous le référencez donc à partir de l’emplacement du composant dans le projet.
Si vous obtenez un 404 lors du chargement du module, vérifiez le chemin et assurez-vous que le fichier se termine par .razor.js, pas seulement .js.
J’espère que vous avez aimé le message ! N’hésitez pas à me contacter sur tous les réseaux sociaux à @emimontesdeoca.