eQuantic.UIeQuantic.UI
Docs
Playground
GitHub
DocsRuntime
Runtime (TypeScript)
Edit this page
6 min read
Le Runtime d'eQuantic.UI est la bibliothèque qui donne vie à l'application dans le navigateur. Il a la charge de transformer l'arbre virtuel que génère le code compilé en vrais éléments du DOM et de réagir aux changements d'état.
📦 Distribution du runtime
Le runtime est distribué comme un unique fichier empaqueté (runtime.js ; sa taille n'est pas citée ici, parce que sa taille gzip est un budget que ServedRuntimeBudgetTests fait respecter, voir Flux de build) qui comprend :
•
Le runtime central : le réconciliateur de DOM virtuel, le cycle de vie des composants
•
La gestion d'état : le système d'état réactif
•
Le système d'événements : le suivi d'événements fondé sur WeakMap
•
Le pont des Server Actions : la communication RPC entre client et serveur
•
Les outils de développement : logger et overlay d'erreurs (développement seulement)
•
Le fournisseur de services : le conteneur d'injection de dépendances
Empaquetage et déploiement
Le runtime voyage dans le paquet qui le sert, eQuantic.UI.Server : le Server embarque le bundle et répond /_equantic/runtime.js avec lui, et porte les mêmes octets sous forme de fichier à tools/runtime/runtime.js. Le SDK copie ce fichier dans le wwwroot/_equantic/ de l'application pendant le build (la cible MSBuild CopyEQuanticRuntime) pour les outils qui chargent les modules d'une application hors d'un serveur, comme l'aperçu de VS Code ; à une application en marche on répond toujours avec le bundle embarqué.
Flux de build :
1
2
3
4
5
6
7
8
9
Source TypeScript (src/eQuantic.UI.Runtime/src) + boot.ts (src/eQuantic.UI.Sdk/Resources)
↓ cible BundleRuntime d'eQuantic.UI.Server (bun embarqué), avant chaque build
src/eQuantic.UI.Server/wwwroot/runtime.js (UN bundle, et son unique écrivain)
├─ embarqué dans eQuantic.UI.Server.dll → servi sur /_equantic/runtime.js
↓ cible CollectServedRuntime, au moment du pack
eQuantic.UI.Server.nupkg/tools/runtime/runtime.js
↓ le SDK le résout via $(PkgeQuantic_UI_Server)
↓ cible MSBuild CopyEQuanticRuntime
wwwroot/_equantic/runtime.js du consommateur (les mêmes octets)
Bénéfices de l'architecture :
•
✅ Un seul écrivain : le bundle est écrit une fois, par le paquet qui le sert ; le SDK ne fait que le référencer
•
✅ La copie EST le runtime servi : ce qu'une application trouve dans wwwroot/_equantic/runtime.js est octet pour octet ce que répond /_equantic/runtime.js
•
✅ Aucune duplication : une seule source de vérité pour runtime.js
•
✅ Zéro dépendance : qui le consomme reçoit le runtime automatiquement, sans Node.js ni npm
🔄 Le réconciliateur
À la différence des frameworks qui recréent tout le DOM, le Reconciler d'eQuantic.UI compare la page actuelle avec la nouvelle version voulue et n'applique que les changements minimaux nécessaires.
Algorithme de diffing :
1.
Comparaison de type : si un nœud a changé de balise (par exemple de div à span), il est remplacé entièrement.
2.
Mise à jour des attributs : seuls les attributs modifiés sont changés dans le DOM.
3.
Gestion des enfants : le réconciliateur parcourt récursivement la liste des enfants.
🗝️ Identité par clé
Le réconciliateur prend en charge le Keyed Diffing par la propriété key.
•
Si deux nœuds à des positions différentes ont la même clé, le framework comprend que l'élément a été déplacé, et préserve l'état interne du navigateur (comme la position du curseur dans un champ ou l'état du défilement).
🧠 Gestion des événements et de la mémoire
Pour prévenir les fuites de mémoire, le runtime utilise un système de suivi d'événements fondé sur WeakMap.
Avantages de WeakMap :
•
Les listeners d'événements sont mappés directement sur l'HTMLElement.
•
Quand un élément est retiré du DOM et qu'il n'y a plus de références vers lui, le ramasse-miettes du navigateur peut nettoyer automatiquement les métadonnées de l'événement, ce qui garantit que la consommation mémoire de l'application reste stable même sur de longues sessions.
🎯 Deux contrats d'événements à connaître
Depuis 0.2.0-preview.24
Le miroir d'HtmlElement abaisse les propriétés on* vers des noms d'événements du DOM, avec l'orthographe propre au DOM là où la seule mise en minuscules se trompe : OnDoubleClick enregistre dblclick (l'unique divergence de l'EventNameMap du C# : un listener doubleclick s'attache très bien et ne se déclenche jamais). Et poser OnSubmit prend la PROPRIÉTÉ de la soumission : le runtime appelle preventDefault() avant d'invoquer, donc la soumission avec navigation propre au navigateur ne tourne jamais, et le gestionnaire valide puis appelle une server action à la place. Un formulaire qui veut la soumission native ne pose simplement aucun gestionnaire. click garde les comportements par défaut du navigateur qu'il a toujours eus : un clic sur un libellé doit encore basculer sa case.
🔒 Gestion du focus modal
Depuis 0.2.0-preview.24
Les couches d'overlay modales arrivent des deux producteurs en portant role="dialog", aria-modal, tabindex="-1" et un marqueur data-eq-trap. Le contrôleur du client réconcilie les pièges contre le DOM au moment même où l'ensemble des Shortcuts se valide après chaque passe du réconciliateur : une couche qui est apparue enregistre qui l'a invoquée et prend le focus après la frame suivante (une couche qui s'estompe depuis visibility:hidden n'est pas focalisable avant que le style ne soit posé) ; Tab et Maj+Tab tournent à l'intérieur, et une garde focusin rattrape ce qui s'échappe ; une couche qui a cessé d'être marquée (retirée, fermée en restant montée, ou reparentée pour son animation de sortie) rend le focus à qui l'a invoquée. La découverte par marqueur plutôt que par chemin est ce qui garde les deux producteurs identiques octet pour octet.
💧 Hydratation (SSR)
Le runtime prend en charge le processus d'"hydratation", où il prend le contrôle du HTML que le serveur a déjà rendu (SSR). Au lieu de détruire et de recréer, le runtime n'attache que les listeners d'événements nécessaires aux éléments existants, ce qui garantit un chargement initial instantané.
🔧 Mode développement
Le runtime détecte l'environnement via le drapeau window.__EQ_DEV__ (posé par le serveur d'après IWebHostEnvironment.IsDevelopment()).
Fonctionnalités réservées au développement
Système de logger (utils/logger.ts)
Système de journalisation professionnel qui n'émet qu'en mode développement :
1
2
3
4
5
6
import { logger } from './utils/logger';
logger.debug('Boot process started'); // Développement seulement
logger.info('Component rendered'); // Développement seulement
logger.warn('Deprecated API used'); // Journalise toujours
logger.error('Failed to load data'); // Journalise toujours
Tous les logs sont préfixés de [eQuantic.UI] pour les filtrer facilement.
Overlay d'erreurs (dev/error-overlay.ts)
Overlay d'erreurs à la manière de Next.js qui affiche les erreurs de runtime dans une interface plein écran (développement seulement) :
•
Capture automatique : erreurs non gérées et rejets de promesses
•
Stack traces : le contexte complet de l'erreur avec l'information de source
•
Prise en charge du clavier : appuyez sur Esc pour fermer
•
UX propre : semblable à l'overlay d'erreurs de Next.js
L'overlay d'erreurs est importé et activé automatiquement quand window.__EQ_DEV__ === true.
Mode production
Dans les builds de production :
•
logger.debug() et logger.info() sont réduits au silence
•
L'overlay d'erreurs n'est jamais chargé
•
Seuls logger.warn() et logger.error() émettent dans la console
•
Surcoût de runtime minimal : un bundle, dont la taille gzip est un budget que la suite fait respecter plutôt qu'un nombre cité ici
🎨 Le pont du thème
Le thème de l'application est du C# typé sur le serveur (IAppTheme, choisi via UseTheme, voir DesignSystem). Le serveur sérialise le thème choisi dans window.__EQ_THEME__ à côté de la configuration de boot, et le pont de thème du runtime (shared/theme-bridge.ts) l'adopte au boot, si bien que les pixels du SSR et le lowering du client résolvent les mêmes tokens, et qu'une bascule clair/sombre à l'exécution retourne une seule déclaration color-scheme.