Skip to content

Runtime pt BR

Edgar Mesquita edited this page Aug 14, 2026 · 3 revisions

Runtime (TypeScript)

🌐 Esta página em: English · Português

O runtime do eQuantic.UI é a biblioteca que dá vida à aplicação no browser. Ele é responsável por transformar a árvore virtual gerada pelo código compilado em elementos DOM reais e por reagir a mudanças de estado.

📦 Distribuição do runtime

O runtime é distribuído como um único arquivo empacotado (runtime.js, ~49KB minificado) que inclui:

  • Núcleo do runtime: reconciliador de DOM virtual, ciclo de vida dos componentes
  • Gestão de estado: sistema de estado reativo
  • Sistema de eventos: rastreamento de eventos baseado em WeakMap
  • Ponte de Server Actions: comunicação RPC cliente-servidor
  • Ferramentas de desenvolvimento: logger e overlay de erro (só em dev)
  • Service Provider: contêiner de injeção de dependência

Empacotamento e entrega

O runtime é autocontido no pacote eQuantic.UI.Runtime, em tools/runtime/runtime.js. O SDK referencia esse pacote e copia o runtime durante o build pelo target MSBuild CopyEQuanticRuntime.

Fluxo de build:

Fonte TypeScript (src/eQuantic.UI.Runtime)
    ↓ npm run build (vite + tsc)
dist/index.js (bundle único via inlineDynamicImports)
    ↓ empacotado no pacote Runtime
eQuantic.UI.Runtime.nupkg/tools/runtime/runtime.js
    ↓ o SDK resolve via $(PkgeQuantic_UI_Runtime)
    ↓ target MSBuild CopyEQuanticRuntime
wwwroot/_equantic/runtime.js do consumidor

Benefícios da arquitetura:

  • Desacoplamento: o runtime gerencia os próprios artefatos, o SDK apenas referencia
  • Versionamento correto: o consumidor pode usar versões do Runtime diferentes das do SDK
  • Sem duplicação: uma única fonte da verdade para o runtime.js
  • Zero dependências: os consumidores recebem o runtime automaticamente, sem Node.js/npm

🔄 O reconciliador

Diferente de frameworks que recriam o DOM inteiro, o Reconciler do eQuantic.UI compara a página atual com a nova versão desejada e aplica só as mudanças mínimas necessárias.

Algoritmo de diffing:

  1. Comparação de tipo: se um nó mudou de tag (ex.: div para span), ele é substituído inteiro.
  2. Atualização de atributos: só os atributos modificados são alterados no DOM.
  3. Gestão de filhos: o reconciliador percorre a lista de filhos recursivamente.

🗝️ Identidade por chave

O reconciliador suporta diffing por chave pela propriedade key.

  • Se dois nós em posições diferentes têm a mesma chave, o framework entende que o elemento foi movido, preservando o estado interno do browser (como a posição do cursor num input ou o estado de rolagem).

🧠 Gestão de eventos e memória

Para evitar vazamentos de memória, o runtime usa um sistema de rastreamento de eventos baseado em WeakMap.

Vantagens do WeakMap:

  • Os listeners de evento são mapeados diretamente ao HTMLElement.
  • Quando um elemento é removido do DOM e não há mais referências a ele, o coletor de lixo do browser pode limpar os metadados de evento automaticamente, garantindo que o consumo de memória da aplicação fique estável mesmo em sessões longas.

🎯 Dois contratos de evento que vale conhecer

Desde 0.2.0-preview.24

O espelho do HtmlElement rebaixa propriedades on* para nomes de evento do DOM, com a grafia do próprio DOM onde só passar para minúsculas está errado: OnDoubleClick registra dblclick (a única divergência do EventNameMap em C#: um listener de doubleclick anexa direitinho e nunca dispara). E definir OnSubmit toma POSSE da submissão: o runtime chama preventDefault() antes de invocar, então a submissão do browser que navega para fora nunca roda, então o handler valida e chama um server action em vez disso. Um formulário que quer a submissão nativa simplesmente não define handler nenhum. O click mantém os padrões do browser que ele sempre teve: um clique num label ainda tem que alternar o checkbox dele.

🔒 Gestão de foco em modais

Desde 0.2.0-preview.24

As camadas de overlay modal chegam dos dois produtores carregando role="dialog", aria-modal, tabindex="-1" e um marcador data-eq-trap. O controller do cliente reconcilia as armadilhas contra o DOM no mesmo momento em que o conjunto de atalhos é comitado depois de cada passada do reconciliador: uma camada que apareceu registra quem a invocou e toma o foco depois do próximo frame (uma camada saindo de visibility:hidden não é focável até o estilo assentar); Tab/Shift+Tab circulam dentro dela, uma guarda de focusin puxa de volta o que escapa; uma camada que deixou de estar marcada (removida, fechada mantendo a montagem, ou reparentada para a animação de saída) devolve o foco a quem a invocou. Descobrir por marcador em vez de por caminho é o que mantém os dois produtores idênticos byte a byte.

💧 Hidratação (SSR)

O runtime suporta o processo de "hidratação", em que ele assume o controle de HTML já renderizado pelo servidor (SSR). Em vez de destruir e recriar, o runtime apenas anexa os listeners de evento necessários aos elementos existentes, garantindo um carregamento inicial instantâneo.

🔧 Modo de desenvolvimento

O runtime detecta o ambiente pela flag window.__EQ_DEV__ (definida pelo servidor com base no IWebHostEnvironment.IsDevelopment()).

Recursos exclusivos de desenvolvimento

Sistema de logging (utils/logger.ts)

Sistema de logging profissional que só imprime em modo de desenvolvimento:

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

logger.debug('Boot process started');  // Só em dev
logger.info('Component rendered');     // Só em dev
logger.warn('Deprecated API used');    // Sempre loga
logger.error('Failed to load data');   // Sempre loga

Todos os logs recebem o prefixo [eQuantic.UI] para facilitar a filtragem.

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

Overlay de erro no estilo Next.js que mostra os erros de runtime numa interface em tela cheia (só em desenvolvimento):

  • Captura automática: erros não tratados e rejeições de promise
  • Stack traces: contexto completo do erro com informação de origem
  • Suporte a teclado: aperte Esc para fechar
  • UX limpa: parecido com o overlay de erro do Next.js

O overlay de erro é importado e ativado automaticamente quando window.__EQ_DEV__ === true.

Modo de produção

Em builds de produção:

  • logger.debug() e logger.info() ficam em silêncio
  • O overlay de erro nunca é carregado
  • logger.warn() e logger.error() escrevem no console
  • Custo mínimo de runtime (~49KB gzipado)

🎨 Ponte de tema

O tema do app é C# tipado no servidor (IAppTheme, selecionado via UseTheme, veja DesignSystem). O servidor serializa o tema selecionado em window.__EQ_THEME__ ao lado da configuração de boot, e a ponte de tema do runtime (shared/theme-bridge.ts) o adota no boot, para que os pixels do SSR e o rebaixamento do cliente resolvam os mesmos tokens, e uma troca claro/escuro em tempo de execução vire uma única declaração color-scheme.

Clone this wiki locally