Présentation de Topcoat
Topcoat est un framework Rust « batteries‑included » destiné aux applications web full‑stack. La version 0.9, publiée en septembre 2026, regroupe un moteur de rendu, un système de composants, un ORM nommé Toasty et un ensemble d’outils pour le courrier électronique. Le projet s’inspire du modèle de productivité de Ruby on Rails tout en conservant les garanties de sécurité et de performance propres à Rust.
Mécanismes de rendu et réactivité
Topcoat privilégie le rendu côté serveur comme point de départ. Le code Rust s’exécute sur le serveur, génère le HTML initial, puis transmet un sous‑ensemble d’expressions runtime vers le navigateur. Ces expressions, écrites dans une syntaxe macro view!, sont entièrement typées et peuvent être transpilées en JavaScript. Elles permettent d’ajouter de la réactivité sans déclencher de requête supplémentaire. Le système de signals stocke l’état côté serveur tout en le répliquant dans le navigateur, comme illustré dans l’exemple ci‑dessous.
#[page]
pub async fn page(cx: &Cx) -> Result<impl View> {
let count = signal(cx, || 0i32);
Ok(view! {
<button @click=$(|_e| count.increment())>increment</button>
<button @click=$(|_e| count.decrement())>decrement</button>
<div>$(count.get())</div>
})
}
Lorsque la logique doit modifier la structure du DOM, Topcoat introduit les shards. Un shard est un composant qui se réexécute sur le serveur dès que ses arguments changent. Le serveur renvoie alors le fragment HTML mis à jour, éliminant ainsi le besoin d’un rafraîchissement complet du client. Cette approche combine la rapidité d’un rendu initial serveur avec la fluidité d’interactions client‑side.
Intégration de l'ORM Toasty et impact sur les performances
Toasty, publié séparément sur crates.io, fournit un accès asynchrone aux bases de données. Dans le code d’exemple, la fonction search_products est appelée depuis un shard, ce qui signifie que chaque modification du signal query déclenche une requête serveur, un rendu de la liste et un renvoi du HTML. La combinaison de Rust et d’un ORM asynchrone maintient l’utilisation mémoire autour de 20 Mo pour une application typique, ce qui reste nettement inférieur aux piles JavaScript classiques.
Le choix de Rust garantit l’absence de garbage collector et une gestion fine des lifetimes, limitant les fuites de mémoire dans les environnements à forte charge. Cependant, la nécessité de compiler chaque shard à chaque changement de signal introduit un coût de latence lié à la compilation JIT du code Rust sur le serveur. Ce coût reste acceptable pour des interactions peu fréquentes, mais peut devenir un facteur limitant dans des scénarios à haute fréquence d’événements.
Analyse des limites et perspectives
Le modèle de Topcoat repose sur une connexion constante entre le client et le serveur pour synchroniser les signaux. Dans des réseaux à latence élevée, la réactivité perçue peut diminuer, même si le rendu HTML reste correct. De plus, la courbe d’apprentissage de Rust, notamment la gestion explicite des lifetimes, peut freiner l’adoption par des équipes habituées à des langages plus permissifs.
Malgré ces contraintes, Topcoat démontre qu’il est possible de construire des applications web complètes avec les garanties de sécurité et de performance de Rust, tout en conservant une ergonomie proche de celle des frameworks dynamiques. L’évolution future du framework devra probablement optimiser le pipeline de recompilation des shards et enrichir les abstractions côté client pour réduire la dépendance au serveur dans les cas d’interaction intensive.