-
Notifications
You must be signed in to change notification settings - Fork 1
PackageArchitecture pt BR
🌐 Esta página em: English · Português
Este documento explica a arquitetura de pacotes do eQuantic.UI e os princípios por trás do design autocontido dela.
Cada pacote do eQuantic.UI é autocontido e gerencia os próprios artefatos. O SDK age como um orquestrador que referencia os outros pacotes pelas propriedades autogeradas do NuGet.
O antipadrão que o design rejeita, o SDK embarcando artefatos de outros pacotes:
eQuantic.UI.Sdk.nupkg ❌
├─ tools/runtime/runtime.js (copiado do Runtime)
└─ tools/StandardComponents/*.cs (copiado do Components)
Por que esse formato falha:
- Acoplamento forte: o SDK conhece diretamente as entranhas do Runtime e do Components
- Conflitos de versão: o consumidor instala o Runtime 0.1.3 mas o SDK contém artefatos embarcados da 0.1.2
- Duplicação de artefatos: os mesmos arquivos existem em vários pacotes
- Inflexível: não dá para atualizar o Runtime ou o Components de forma independente sem republicar o SDK
eQuantic.UI.Runtime.nupkg ✅
└─ tools/runtime/runtime.js (autogerido)
eQuantic.UI.Components.nupkg ✅
└─ tools/source/*.cs (autogerido)
eQuantic.UI.Sdk.nupkg ✅
├─ Sdk/Sdk.props (inclui Core, Components, Server e Runtime automaticamente)
└─ Sdk/Sdk.targets (referencia os pacotes pelas propriedades $(Pkg*))
Benefícios:
- ✅ Desacoplamento: cada pacote possui e gerencia os artefatos dele
- ✅ Versionamento correto: a versão instalada pelo consumidor é sempre a usada
- ✅ Sem duplicação: uma única fonte da verdade por artefato
- ✅ Evolução independente: os pacotes podem ser atualizados separadamente
- ✅ Interface clara: o SDK usa propriedades bem definidas do NuGet
Propósito: abstrações e tipos centrais
Contém:
- A interface
IComponent - Os tipos base
HtmlNode,HtmlElement - Abstrações de ciclo de vida de componente
- Contexto de renderização
Empacota: apenas a DLL compilada (sem artefatos adicionais)
Propósito: a biblioteca de componentes padrão (Button, Input, Container, etc.)
Contém:
- A DLL compilada para uso em tempo de execução
- Os arquivos de código (
tools/source/*.cs) para a resolução de tipos do compilador
Empacotamento:
<!-- eQuantic.UI.Components.csproj -->
<ItemGroup>
<Content Include="**\*.cs" Exclude="obj\**;bin\**"
PackagePath="tools\source\" />
</ItemGroup>Por que arquivos de código?
O compilador (eqc.dll) precisa de acesso ao código dos componentes para resolver tipos externos durante a compilação. Quando um consumidor usa <Button>, o compilador procura a definição da classe Button no pacote Components.
Uso pelo SDK:
<!-- Resolvido automaticamente pelo NuGet -->
<PropertyGroup>
<_ComponentsSource>$(PkgeQuantic_UI_Components)/tools/source</_ComponentsSource>
</PropertyGroup>
<!-- Passado ao compilador -->
<Exec Command="dotnet eqc.dll "$(ProjectDir);$(_ComponentsSource)" ..." />Propósito: o runtime do browser (DOM virtual, reconciliador, gestão de estado)
Contém:
- O runtime TypeScript/JavaScript compilado com o Vite
-
runtime.js (
tools/runtime/runtime.js) - arquivo único empacotado (~49KB)
Empacotamento:
<!-- eQuantic.UI.Runtime.csproj -->
<ItemGroup>
<Content Include="dist\index.js"
PackagePath="tools\runtime\runtime.js"
Condition="Exists('dist\index.js')" />
</ItemGroup>Processo de build:
- Código TypeScript →
npm run build(Vite + tsc) - Saída:
dist/index.js(bundle único viainlineDynamicImports) - Empacotado:
eQuantic.UI.Runtime.nupkg/tools/runtime/runtime.js
Uso pelo SDK:
<!-- Resolvido automaticamente pelo NuGet -->
<PropertyGroup>
<_RuntimeSource>$(PkgeQuantic_UI_Runtime)/tools/runtime/runtime.js</_RuntimeSource>
</PropertyGroup>
<!-- Copiado para o wwwroot do consumidor -->
<Copy SourceFiles="$(_RuntimeSource)"
DestinationFiles="wwwroot/_equantic/runtime.js" />Propósito: executáveis do Bun específicos de plataforma (Osx64, Win64, Linux64)
Contém:
- O executável do Bun (compactado) para o empacotamento
- Binários específicos de plataforma (~60MB cada)
Por que pacotes separados?
- Os consumidores só baixam o executável da plataforma deles
- Reduz o tamanho do pacote (não é preciso ter as 3 plataformas)
- Separação limpa entre a lógica de runtime e as ferramentas de build
Propósito: integração com o ASP.NET Core
Contém:
- Renderização no servidor (SSR)
- O sistema de RPC dos Server Actions
- Middleware e roteamento
- O runtime.js embarcado, servido em
/_equantic/runtime.js
Nota: o Server embarca a própria cópia do runtime.js como EmbeddedResource para servir por HTTP. Isso é separado da cópia de tempo de build do consumidor.
Propósito: o orquestrador do SDK MSBuild
Contém:
-
Sdk.props- inclui automaticamente os pacotes Core, Components, Server e Runtime -
Sdk.targets- os targets MSBuild de compilação, empacotamento e geração de CSS -
tools/net10.0/eqc.dll- o executável do compilador
NÃO contém:
- ❌ Artefatos do runtime (referencia o pacote Runtime)
- ❌ Código dos componentes (referencia o pacote Components)
Responsabilidades:
-
Gestão de pacotes: inclui automaticamente os pacotes necessários pelo
Sdk.props - Orquestração do build: coordena compilação, empacotamento e geração de CSS
- Resolução de artefatos: resolve o runtime.js e as fontes dos componentes a partir dos pacotes deles
-
Ferramental: fornece o compilador (
eqc.dll) e a infraestrutura de build
Propósito: provedores de conjuntos de ícones
Contêm:
- Lógica de resolução de SVG
- Componentes de ícone especializados
- Implementação de
IIconProvider -
API fluente: registra a si mesmo pela extensão
Use{Name}Icons()sobre oUIOptions.
Propósito: componentes de gráfico especializados
Contêm:
- Wrappers de gráfico
- Declarações de asset via
IRequireAssets -
API fluente: registra a si mesmo pelas extensões
UseChartJs()/UseApexCharts()sobre oUIOptions.
O NuGet gera automaticamente propriedades $(Pkg*) para os pacotes instalados:
<!-- Autogerado em obj/*.nuget.g.props -->
<PropertyGroup>
<PkgeQuantic_UI_Core>/Users/name/.nuget/packages/equantic.ui.core/0.1.2</PkgeQuantic_UI_Core>
<PkgeQuantic_UI_Components>/Users/name/.nuget/packages/equantic.ui.components/0.1.2</PkgeQuantic_UI_Components>
<PkgeQuantic_UI_Runtime>/Users/name/.nuget/packages/equantic.ui.runtime/0.1.2</PkgeQuantic_UI_Runtime>
<PkgeQuantic_UI_Runtime_Osx64>/Users/name/.nuget/packages/equantic.ui.runtime.osx64/0.1.2</PkgeQuantic_UI_Runtime_Osx64>
</PropertyGroup>O SDK usa essas para resolver artefatos:
<!-- Sdk/Sdk.targets -->
<Target Name="CopyEQuanticRuntime">
<PropertyGroup>
<_RuntimeSource>$(PkgeQuantic_UI_Runtime)/tools/runtime/runtime.js</_RuntimeSource>
</PropertyGroup>
<Copy SourceFiles="$(_RuntimeSource)" DestinationFiles="..." />
</Target>Benefícios:
- ✅ O SDK não precisa conhecer os detalhes de estrutura dos pacotes
- ✅ Funciona com qualquer versão de pacote que o consumidor instale
- ✅ Resolução de cache automática pelo NuGet
- ✅ Nenhum caminho fixo
Os pacotes podem evoluir de forma independente:
<!-- O consumidor pode misturar versões -->
<PackageReference Include="eQuantic.UI.Core" Version="0.1.3" />
<PackageReference Include="eQuantic.UI.Runtime" Version="0.1.4" />
<PackageReference Include="eQuantic.UI.Sdk" Version="0.1.2" />O SDK vai usar:
- O runtime.js do Runtime 0.1.4 (não a cópia embarcada da 0.1.2)
- Os arquivos de código do Components 0.1.3 (não a cópia embarcada da 0.1.2)
Por simplicidade, o Sdk.props do SDK define uma versão padrão:
<!-- Sdk/Sdk.props -->
<PropertyGroup>
<EQuanticUIVersion>0.1.2</EQuanticUIVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="eQuantic.UI.Core" Version="$(EQuanticUIVersion)" />
<PackageReference Include="eQuantic.UI.Components" Version="$(EQuanticUIVersion)" />
<PackageReference Include="eQuantic.UI.Runtime" Version="$(EQuanticUIVersion)" />
<PackageReference Include="eQuantic.UI.Server" Version="$(EQuanticUIVersion)" />
</ItemGroup>Os usuários podem sobrepor:
<PropertyGroup>
<EQuanticUIVersion>0.1.5</EQuanticUIVersion>
</PropertyGroup>Ou especificar versões manualmente:
<ItemGroup>
<PackageReference Include="eQuantic.UI.Runtime" Version="0.1.6" />
</ItemGroup>dotnet restore
↓ O NuGet instala os pacotes no cache
~/.nuget/packages/equantic.ui.runtime/0.1.2/
~/.nuget/packages/equantic.ui.components/0.1.2/
↓ O NuGet gera as propriedades $(Pkg*)
obj/project.nuget.g.props
↓ O SDK resolve os artefatos
O Sdk.targets usa $(PkgeQuantic_UI_Runtime)/tools/runtime/runtime.js
Árvore de código em: /Users/name/equantic-ui/
↓ Pacotes locais em: artifacts/packages/
↓ O NuGet.config prioriza o local
<packageSources>
<add key="local" value="../../artifacts/packages" />
</packageSources>
↓ Caminhos alternativos no Sdk.targets
<_RuntimeSource Condition="'$(PkgeQuantic_UI_Runtime)' == ''">
$(MSBuildThisFileDirectory)../../eQuantic.UI.Runtime/dist/index.js
</_RuntimeSource>
Benefícios:
- Quem desenvolve o framework pode trabalhar direto no código
- Não é preciso empacotar/restaurar a cada mudança
- Os mesmos targets funcionam nos dois cenários
-
Deixe cada pacote gerenciar os próprios artefatos
- O Runtime empacota o runtime.js
- O Components empacota os arquivos de código
-
Referencie pelas propriedades do NuGet
- Use
$(PkgeQuantic_UI_*)em vez de caminhos fixos
- Use
-
Forneça alternativas de desenvolvimento
- Permita que o SDK encontre os artefatos na árvore de código ao desenvolver o framework
-
Inclua mensagens de erro claras
- Diga aos usuários qual pacote está faltando quando os artefatos não forem encontrados
-
Não embarque artefatos de outros pacotes
- O SDK NÃO deve copiar o runtime.js do Runtime para dentro dele
-
Não use caminhos relativos entre pacotes
- Ruim:
$(MSBuildThisFileDirectory)../../../Runtime/dist/ - Bom:
$(PkgeQuantic_UI_Runtime)/tools/runtime/
- Ruim:
-
Não assuma que as versões dos pacotes batem
- O consumidor pode usar Runtime 0.1.3 + SDK 0.1.2
-
Não crie dependências circulares
- Os pacotes devem ter um grafo de dependências claro
Error: eQuantic.UI: Runtime not found. Ensure eQuantic.UI.Runtime package is installed.
Causa: $(PkgeQuantic_UI_Runtime) está vazio
Correção:
dotnet restore --force
# Confira que o pacote Runtime está instalado
ls ~/.nuget/packages/equantic.ui.runtime/0.1.2/Error: eQuantic.UI: Standard components not found. Ensure eQuantic.UI.Components package is installed.
Causa: $(PkgeQuantic_UI_Components) está vazio
Correção:
dotnet restore --force
# Verifique se o pacote Components tem os arquivos de código
ls ~/.nuget/packages/equantic.ui.components/0.1.2/tools/source/Sintoma: o build usa um runtime.js velho apesar de o pacote Runtime ter sido atualizado
Causa: o cache do NuGet não foi limpo
Correção:
# Limpe o pacote específico do cache
rm -rf ~/.nuget/packages/equantic.ui.runtime/0.1.2
# Force a restauração
dotnet restore --force --no-cache- Fluxo de build - o pipeline de build completo
- Runtime - a arquitetura e a distribuição do runtime
- Compilador - como o compilador de C# para JS funciona
🌐 English · Português
🏁 Comece aqui
📱 Write-once
- Componentes write-once
- Superfície declarativa
- Motor Photon
- Design System
- Capacidades
- Armazenamento
- Formulários
- Editor de código
- Markdown
- Mermaid
- Renderização de Email
🏗️ Arquitetura
⚙️ Compilação
- Compilador
- Avaliação em tempo de compilação
- Recursos C# suportados
- Resolução de tipos externos
- Fluxo de build
- Diagnósticos
⚡ Runtime
🔌 Servidor
🎨 Ecossistema
🚀 Desenvolvimento