Runtime (TypeScript)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 :
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
À 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.
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.
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.
•
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.
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.
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é.
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 :
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.
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 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.