Skip to content

Runtime es

Edgar Mesquita edited this page Oct 13, 2026 · 1 revision

Runtime (TypeScript)

🌐 Esta página en: English · Português · Español · Français · Deutsch

El Runtime de eQuantic.UI es la biblioteca que da vida a la aplicación en el navegador. Es responsable de transformar el árbol virtual que genera el código compilado en elementos del DOM reales y de reaccionar a los cambios de estado.

📦 Distribución del runtime

El runtime se distribuye como un único archivo empaquetado (runtime.js; su tamaño no se cita aquí, porque su tamaño gzip es un presupuesto que ServedRuntimeBudgetTests hace cumplir, vea Flujo de build) que incluye:

  • Runtime central: el reconciliador de DOM virtual, el ciclo de vida de los componentes
  • Gestión de estado: el sistema de estado reactivo
  • Sistema de eventos: el seguimiento de eventos basado en WeakMap
  • Puente de Server Actions: la comunicación RPC entre cliente y servidor
  • Herramientas de desarrollo: logger y overlay de errores (solo en desarrollo)
  • Proveedor de servicios: el contenedor de inyección de dependencias

Empaquetado y despliegue

El runtime viaja dentro del paquete que lo sirve, eQuantic.UI.Server: el Server incrusta el bundle y responde /_equantic/runtime.js con él, y lleva los mismos bytes como archivo en tools/runtime/runtime.js. El SDK copia ese archivo al wwwroot/_equantic/ de la aplicación durante el build (el target de MSBuild CopyEQuanticRuntime) para las herramientas que cargan los módulos de una aplicación fuera de un servidor, como la vista previa de VS Code; a una aplicación en marcha siempre se le responde con el bundle incrustado.

Flujo de build:

Fuente TypeScript (src/eQuantic.UI.Runtime/src) + boot.ts (src/eQuantic.UI.Sdk/Resources)
    ↓ target BundleRuntime de eQuantic.UI.Server (bun embebido), antes de cada build
src/eQuantic.UI.Server/wwwroot/runtime.js (UN bundle, y su único escritor)
    ├─ incrustado en eQuantic.UI.Server.dll → servido en /_equantic/runtime.js
    ↓ target CollectServedRuntime, al empaquetar
eQuantic.UI.Server.nupkg/tools/runtime/runtime.js
    ↓ el SDK lo resuelve vía $(PkgeQuantic_UI_Server)
    ↓ target de MSBuild CopyEQuanticRuntime
wwwroot/_equantic/runtime.js del consumidor (los mismos bytes)

Beneficios de la arquitectura:

  • ✅ Un solo escritor: el bundle se escribe una vez, por el paquete que lo sirve; el SDK solo lo referencia
  • ✅ La copia ES el runtime servido: lo que una aplicación encuentra en wwwroot/_equantic/runtime.js es byte por byte lo que responde /_equantic/runtime.js
  • ✅ Sin duplicación: una única fuente de verdad para runtime.js
  • ✅ Cero dependencias: quien lo consume recibe el runtime automáticamente, sin Node.js ni npm

🔄 El reconciliador

A diferencia de los frameworks que recrean el DOM entero, el Reconciler de eQuantic.UI compara la página actual con la nueva versión deseada y aplica solo los cambios mínimos necesarios.

Algoritmo de diffing:

  1. Comparación de tipo: si un nodo cambió de etiqueta (por ejemplo, de div a span), se reemplaza por completo.
  2. Actualización de atributos: solo los atributos modificados se cambian en el DOM.
  3. Gestión de hijos: el reconciliador recorre recursivamente la lista de hijos.

🗝️ Identidad por clave

El reconciliador soporta el Keyed Diffing a través de la propiedad key.

  • Si dos nodos en posiciones distintas tienen la misma clave, el framework entiende que el elemento se movió, y preserva el estado interno del navegador (como la posición del cursor en un campo o el estado del scroll).

🧠 Gestión de eventos y de memoria

Para prevenir fugas de memoria, el runtime usa un sistema de seguimiento de eventos basado en WeakMap.

Ventajas de WeakMap:

  • Los listeners de eventos se mapean directamente al HTMLElement.
  • Cuando un elemento se retira del DOM y no quedan más referencias a él, el recolector de basura del navegador puede limpiar automáticamente los metadatos del evento, lo que asegura que el consumo de memoria de la aplicación se mantenga estable incluso en sesiones largas.

🎯 Dos contratos de eventos que vale conocer

Desde 0.2.0-preview.24

El espejo de HtmlElement baja las propiedades on* a nombres de eventos del DOM, con la grafía propia del DOM allí donde pasarlo a minúsculas no basta: OnDoubleClick registra dblclick (la única divergencia del EventNameMap de C#: un listener de doubleclick se engancha bien y no se dispara nunca). Y fijar OnSubmit toma la PROPIEDAD del envío: el runtime llama a preventDefault() antes de invocar, así que el envío con navegación propio del navegador nunca corre, y el manejador valida y llama a una server action en su lugar. Un formulario que quiere el envío nativo simplemente no fija ningún manejador. click conserva los valores por defecto del navegador que siempre tuvo: un clic en una etiqueta debe seguir alternando su casilla.

🔒 Gestión del foco modal

Desde 0.2.0-preview.24

Las capas de overlay modales llegan de los dos productores llevando role="dialog", aria-modal, tabindex="-1" y un marcador data-eq-trap. El controlador del cliente reconcilia las trampas contra el DOM en el mismo momento en que el conjunto de Shortcuts se confirma después de cada pasada del reconciliador: una capa que apareció registra a quien la invocó y toma el foco después del siguiente frame (una capa que se desvanece desde visibility:hidden no es enfocable hasta que el estilo aterriza); Tab y Shift+Tab circulan dentro, y una guarda de focusin recupera lo que se escapa; una capa que dejó de estar marcada (retirada, cerrada manteniéndose montada, o reparentada para su animación de salida) devuelve el foco a quien la invocó. Descubrir por marcador en lugar de por ruta es lo que mantiene a los dos productores idénticos byte a byte.

💧 Hidratación (SSR)

El runtime soporta el proceso de "hidratación", en el que toma el control del HTML que el servidor ya renderizó (SSR). En lugar de destruir y recrear, el runtime solo engancha los listeners de eventos necesarios a los elementos existentes, lo que asegura una carga inicial instantánea.

🔧 Modo de desarrollo

El runtime detecta el entorno vía el flag window.__EQ_DEV__ (que fija el servidor a partir de IWebHostEnvironment.IsDevelopment()).

Funcionalidades solo de desarrollo

Sistema de logger (utils/logger.ts)

Sistema de logging profesional que solo emite en modo de desarrollo:

import { logger } from './utils/logger';

logger.debug('Boot process started');  // Solo en desarrollo
logger.info('Component rendered');     // Solo en desarrollo
logger.warn('Deprecated API used');    // Siempre registra
logger.error('Failed to load data');   // Siempre registra

Todos los logs llevan el prefijo [eQuantic.UI] para filtrarlos con facilidad.

Overlay de errores (dev/error-overlay.ts)

Overlay de errores al estilo de Next.js que muestra los errores de runtime en una interfaz a pantalla completa (solo en desarrollo):

  • Captura automática: errores no manejados y rechazos de promesas
  • Stack traces: el contexto completo del error con información de la fuente
  • Soporte de teclado: pulsa Esc para cerrar
  • UX limpia: similar al overlay de errores de Next.js

El overlay de errores se importa y se activa automáticamente cuando window.__EQ_DEV__ === true.

Modo de producción

En los builds de producción:

  • logger.debug() y logger.info() quedan silenciados
  • El overlay de errores nunca se carga
  • Solo logger.warn() y logger.error() emiten a la consola
  • Coste mínimo de runtime: un bundle, cuyo tamaño gzip es un presupuesto que la suite hace cumplir, en lugar de un número citado aquí

🎨 Puente del tema

El tema de la aplicación es C# tipado en el servidor (IAppTheme, seleccionado vía UseTheme, vea DesignSystem). El servidor serializa el tema seleccionado en window.__EQ_THEME__ al lado de la configuración de boot, y el puente de tema del runtime (shared/theme-bridge.ts) lo adopta en el boot, así que los píxeles del SSR y el lowering del cliente resuelven los mismos tokens, y un cambio claro/oscuro en tiempo de ejecución voltea una sola declaración color-scheme.

Clone this wiki locally