Repository navigation
PackageArchitecture de
🌐 Diese Seite auf: English · Português · Español · Français · Deutsch
Dieses Dokument erklärt die Paketarchitektur von eQuantic.UI und die Prinzipien hinter ihrem eigenständigen Entwurf.
Jedes eQuantic.UI-Paket ist eigenständig und verwaltet seine eigenen Artefakte. Das SDK wirkt als Orchestrator, der die anderen Pakete über die von NuGet selbst erzeugten Eigenschaften referenziert.
Das Antipattern, das der Entwurf ablehnt, nämlich das SDK, das Artefakte anderer Pakete einbettet:
eQuantic.UI.Sdk.nupkg ❌
├─ tools/runtime/runtime.js (aus Server kopiert)
└─ tools/StandardComponents/*.cs (aus Components kopiert)
Warum diese Form scheitert:
- Enge Kopplung: Das SDK kennt die Innereien von Server und Components direkt
- Versionskonflikte: Der Konsument stellt eine Server-Version wieder her, und das SDK trägt eine Kopie einer anderen
- Artefakt-Duplikation: Dieselben Dateien liegen in mehreren Paketen
- Unflexibel: Server oder Components lassen sich nicht aktualisieren, ohne das SDK neu zu veröffentlichen
eQuantic.UI.Server.nupkg ✅
├─ lib/net10.0/eQuantic.UI.Server.dll (bettet die Runtime ein, die es auf /_equantic/runtime.js ausliefert)
└─ tools/runtime/runtime.js (dieselben Bytes, damit das SDK sie kopiert)
eQuantic.UI.Components.nupkg ✅
└─ tools/source/*.cs (selbst verwaltet)
eQuantic.UI.Sdk.nupkg ✅
├─ Sdk/Sdk.props (nimmt von selbst Primitives, Code, Components, Charts, Web, Server,
│ das Bun-Paket der Plattform und den Generators-Analyzer auf)
├─ Sdk/Sdk.targets (löst die Artefakte der anderen Pakete über $(Pkg*)-Eigenschaften auf)
├─ tools/net10.0/ (eqc und eqicon, die zwei Build-Werkzeuge, die das SDK ausführt)
└─ tools/netstandard2.0/ (die Tasks, die sie starten, und jedes andere Programm, ohne Shell)
Vorteile:
- ✅ Entkopplung: Jedes Paket besitzt und verwaltet seine Artefakte
- ✅ Korrekte Versionierung: Es wird immer die vom Konsumenten installierte Version verwendet
- ✅ Keine Duplikation: eine einzige Quelle der Wahrheit je Artefakt
- ✅ Unabhängige Entwicklung: Pakete können getrennt aktualisiert werden
- ✅ Klare Schnittstelle: Das SDK nutzt klar definierte NuGet-Eigenschaften
Es gibt kein Paket eQuantic.UI.Core. Es wurde in die Assemblys aufgelöst, die seine Teile besaßen:
Die DOM-Oberfläche ging an Web, die Kontraktattribute an Primitives, Metadaten und Assets an
Server, der Zustand der Bildoptimierung an Images. Eine Seite, die eQuantic.UI.Core wegen
[Page] oder [ServerAction] importierte, löscht die Zeile: Der Namespace, den sie für das
Vokabular schon importiert, trägt sie.
Zweck: das abstrakte Vokabular und die Kontrakte
Enthält:
- Das visuelle Vokabular, gegen das eine Komponente geschrieben wird: Knoten, Layout, typisierte Styles, Tokens, Theme
- Die Komponentenbasen,
StatelessComponentundStatefulComponent - Die Kontraktattribute:
[Page],[ServerAction],[ServerOnly],[Authorize],[AllowAnonymous],[FormModel],[UiFactory]
Paketiert: nur die kompilierte DLL (keine weiteren Artefakte). Null Abhängigkeiten.
Zweck: der Web-Realisierer und die DOM-Notluke
Enthält:
- Den Realisierer, der die gemeinsamen Komponenten zu DOM und atomarem CSS absenkt
- Die Notluke:
HtmlElement,HtmlNode,HtmlStyle,DynamicElement,IComponent,RenderContext,ClassBuilder
Paketiert: nur die kompilierte DLL (keine weiteren Artefakte)
Zweck: die Write-once-Komponentenbibliothek (Button, Input, Card usw.), gegen Primitives geschrieben und je Ziel realisiert
Enthält:
- Die kompilierte DLL für die Laufzeitnutzung
-
Quelldateien (
tools/source/*.cs) für die Typauflösung des Compilers, mit dem eigenen.resxdes SDK neben seinem Designer
Paketierung:
<!-- eQuantic.UI.Components.csproj -->
<ItemGroup>
<Content Include="**\*.cs" Exclude="obj\**;bin\**" PackagePath="tools\source\" />
<Content Include="SdkResources*.resx" PackagePath="tools\source\" />
</ItemGroup>Warum Quelldateien?
Der Compiler (eqc.dll) baut ein semantisches Modell der Seite, die er transpiliert, und dieses
Modell braucht die Definitionen der Komponenten: Wenn eine Seite Button(…) komponiert, liest der
Compiler die Klasse Button aus den Components-Quellen. Das JavaScript der Bibliothek wird NICHT je
Anwendung kompiliert: Die transpilierten Module reisen in runtime.js mit, und eqc leitet die
Imports von using eQuantic.UI.Components dorthin.
Nutzung durch das SDK:
<!-- Sdk/Sdk.targets, Target CompileEQuanticUI -->
<_StandardComponentsDir Condition="'$(PkgeQuantic_UI_Components)' != ''">$(PkgeQuantic_UI_Components)/tools/source</_StandardComponentsDir>
<_EqcSourceDirs>$(MSBuildProjectDirectory);$(_StandardComponentsDir)</_EqcSourceDirs>
<!-- Dem Compiler in einer Antwortdatei übergeben, ein Argument je Zeile, mit genau den Assemblys,
gegen die csc kompiliert (refs). eqc wird mit RunProgram gestartet, dem Compiler und dieser
Datei als Argumentliste, also liest unterwegs keine Shell einen Pfad oder einen Namen -->
<RunProgram Program="dotnet" Arguments="@(_EqcStartArgument)" />Zweck: das TypeScript der Browser-Runtime (virtuelles DOM, Reconciler, Zustandsverwaltung) und ihr Beweis
Paketiert: nichts. Das Projekt wird nicht gepackt (IsPackable=false): Das Bundle, das eine
Anwendung ausführt, schreibt eQuantic.UI.Server aus boot.ts, das dieses TypeScript importiert,
und jenes Paket trägt es (siehe unten). Was das Projekt ausführt, ist der Beweis der Runtime, über
das eingebettete Bun: dotnet build src/eQuantic.UI.Runtime -t:TestRuntime installiert die
Abhängigkeiten aus bun.lock wie festgenagelt, prüft die Typen mit tsc und lässt vitest einmal
laufen.
Zweck: das eingebettete Bun, ein Paket je Betriebssystem und Architektur: Osx64, OsxArm64, Win64, WinArm64, Linux64, LinuxArm64
Enthält:
- Die Bun-Binary, gezippt (
tools/bun/bun-darwin.zip,bun-linux.zipoderbun.exe.zip); das SDK entpackt sie beim ersten Build - Nichts weiter. Die Pakete deklarieren keine Abhängigkeiten
Warum getrennte Pakete?
-
Sdk.propsreferenziert genau EINES von ihnen, gewählt über[MSBuild]::IsOSPlatformund dieOSArchitectureder Maschine, also lädt ein Konsument eine Binary herunter, nie sechs - Klare Trennung zwischen Runtime-Logik und Build-Werkzeugen
- Version und SHA-256 jedes Zips sind in
bun-toolchain.jsonfestgenagelt und werden von den Tests geprüft. Siehe Build-Ablauf
Zweck: die ASP.NET-Core-Integration
Enthält:
- Serverseitiges Rendering (SSR)
- Das RPC-System der Server Actions
- Middleware und Routing
- Metadaten (
SeoBuilder,MetaTags,IHandleMetadata) und Assets (IRequireAssets,AssetBuilder) - Die eingebettete runtime.js, ausgeliefert auf
/_equantic/runtime.js -
tools/runtime/runtime.js: dieselben Bytes als Datei, damit das SDK sie neben die Module einer Anwendung kopiert
Hinweis: Der Server ist der einzige Schreiber der Runtime. Sein Target BundleRuntime bündelt
boot.ts vor jedem Build in wwwroot/runtime.js; der Compiler bettet diese Datei als
EmbeddedResource ein, und das ist, was /_equantic/runtime.js beantwortet, und das Pack-Target
CollectServedRuntime legt dieselbe Datei nach tools/runtime/runtime.js. Die Kopie, die der Build
des Konsumenten verwendet, ist diese Datei, Byte für Byte.
Zweck: der Source-Generator, der die deklarative Factory-Oberfläche für die Komponenten der ANWENDUNG selbst schreibt
Enthält:
- Nur den Generator.
Sdk.propsliefert ihn als Analyzer (PrivateAssets="all"), er ist also eine Abhängigkeit zur Build-Zeit, und nichts von ihm geht mit der Anwendung aus - Abschaltbar mit
<EQuanticGenerateFactorySurface>false</EQuanticGenerateFactorySurface>. Siehe Deklarative Oberfläche
Zweck: der Orchestrator des MSBuild-SDK
Enthält:
-
Sdk.props- nimmt von selbst Primitives, Code, Components, Charts, Web, Server, das Bun-Paket der Plattform und den Generators-Analyzer auf -
Sdk.targets- die MSBuild-Targets für die Kompilierung, das Kopieren von runtime.js, den Vektorkatalog und das Icon der Web-Anwendung -
tools/net10.0/eqc.dll- die Compiler-Binary (ProjekteQuantic.Build) -
tools/net10.0/eqicon.dll- das Icon-Werkzeug (ProjekteQuantic.UI.Native.Build):Assets/**/*.svg→Vectors.g.cs, und das Anwendungs-Icon →wwwroot/_equantic/icons -
tools/netstandard2.0/eQuantic.UI.Sdk.Tasks.dll- die MSBuild-Tasks, mit denen das SDK jedes Programm startet (ProjekteQuantic.UI.Sdk.Tasks):RunProgram, ein Programm und eine Argumentliste ohne Shell, undLinkDirectory, dernode_modules-Link, den einBunPackagebraucht. netstandard2.0 ist das, was jedes MSBuild lädt, das des .NET-SDK und das von Visual Studio (Seit 0.2.0-preview.62)
Die zwei Werkzeuge und die Tasks erreichen tools/ als Kanten des eigenen Build-Graphen des
SDK-Projekts: ProjectReference-Items mit ReferenceOutputAssembly="false" und
PrivateAssets="All", deren Ausgabe das Pack-Target CollectBuildOutput einsammelt. Nichts linkt
gegen sie, und das Paket gewinnt keine Abhängigkeit.
Enthält NICHT:
- ❌ Runtime-Artefakte (es referenziert das Server-Paket)
- ❌ die Components-Quellen (es referenziert das Components-Paket)
Zuständigkeiten:
-
Paketverwaltung: nimmt die benötigten Pakete über
Sdk.propsvon selbst auf - Build-Orchestrierung: koordiniert Kompilierung, Bündelung und Asset-Erzeugung
- Artefaktauflösung: löst runtime.js und die Komponentenquellen aus ihren Paketen auf
-
Werkzeuge: stellt den Compiler (
eqc.dll) und das Icon-Werkzeug (eqicon.dll) bereit
Zweck: dasselbe SDK für Geräte (macOS, iOS, Android). Siehe Photon
Es beantwortet die zwei Fragen von oben genauso: Die Geschwisterpakete lösen sich auf die Version des
SDK selbst auf, und das Werkzeug, das es ausführt (eqicon, für das Anwendungs-Icon, das Bundle und
das Fähigkeiten-Manifest), ist entweder das, was der Quellbaum gerade gebaut hat, oder das, was das
Paket unter tools/net10.0/ ausgeliefert hat.
Zweck: Icon-Kataloge
Enthält:
- Ein generiertes
IconGlyphje Icon, als Eigenschaft, damit der Trimmer die wegwerfen kann, die niemand nennt: Write-once-Daten, im Web und auf Native gleichermaßen genutzt - Einen
EQuanticIconPack.markerin der Quellwurzel. Das SDK entdeckt ein referenziertes Pack an diesem Marker und übergibt seine Quellen eqc als Referenzquellen, sodass eine Glyphe an der Verwendungsstelle eingesetzt wird und kein JavaScript-Modul je Pack ausgeliefert wird - Kein Registrierungsaufruf: Das Paket zu referenzieren ist die ganze Einrichtung. Siehe Icons
Zweck: spezialisierte Diagrammkomponenten
Enthält:
- Diagramm-Hüllen
- Asset-Deklarationen über
IRequireAssets -
Fluent API: Es registriert sich selbst über die Erweiterungen
UseChartJs()/UseApexCharts()aufUIOptions.
NuGet erzeugt eine $(Pkg*)-Eigenschaft für ein installiertes Paket NUR dann, wenn seine
PackageReference GeneratePathProperty="true" trägt. Sdk.props setzt das genau auf den Paketen,
deren INHALT die Targets lesen, nämlich Components, Charts, Server und das Bun-Paket der Plattform:
<!-- Automatisch erzeugt in obj/*.nuget.g.props -->
<PropertyGroup>
<PkgeQuantic_UI_Components>/Users/name/.nuget/packages/equantic.ui.components/<version></PkgeQuantic_UI_Components>
<PkgeQuantic_UI_Charts>/Users/name/.nuget/packages/equantic.ui.charts/<version></PkgeQuantic_UI_Charts>
<PkgeQuantic_UI_Server>/Users/name/.nuget/packages/equantic.ui.server/<version></PkgeQuantic_UI_Server>
<PkgeQuantic_UI_Runtime_OsxArm64>/Users/name/.nuget/packages/equantic.ui.runtime.osxarm64/<version></PkgeQuantic_UI_Runtime_OsxArm64>
</PropertyGroup>Das SDK nutzt sie, um Artefakte aufzulösen:
<!-- Sdk/Sdk.targets -->
<Target Name="CopyEQuanticRuntime">
<PropertyGroup>
<_RuntimeSourcePath>$(PkgeQuantic_UI_Server)/tools/runtime/runtime.js</_RuntimeSourcePath>
</PropertyGroup>
<Copy SourceFiles="$(_RuntimeSourcePath)" DestinationFiles="..." />
</Target>Vorteile:
- ✅ Das SDK muss die Strukturdetails des Pakets nicht kennen
- ✅ Funktioniert mit jeder Paketversion, die der Konsument installiert
- ✅ Automatische Cache-Auflösung durch NuGet
- ✅ Keine hart verdrahteten Pfade
Jedes Paket wird aus EINER Zeile in der Directory.Build.props des Repositorys versioniert, und ein
Release-Tag veröffentlicht sie alle in dieser Version. Die aktuelle Nummer wird hier mit Absicht
nicht genannt: Sie ändert sich mit jedem Release, und eine veraltete Nummer in der Dokumentation ist
die Art, wie eine Leserin irregeführt wird. Lesen Sie die Datei.
Sdk.props liest die Version aus dem nuspec des installierten SDK-Pakets selbst und fordert jedes
Geschwister in dieser Version an. Der Rückfall ist ein Platzhalter, also scheitert ein Build nie am
Fehlen einer Nummer:
<!-- Sdk/Sdk.props -->
<PropertyGroup Condition="'$(EQuanticUIVersion)' == '' AND Exists('$(_EQuanticSdkNuspecPath)')">
<EQuanticUIVersion>$([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText('$(_EQuanticSdkNuspecPath)')),
'<version>(.+?)</version>').Groups[1].Value)</EQuanticUIVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(EQuanticUIVersion)' == ''">
<EQuanticUIVersion>*</EQuanticUIVersion>
</PropertyGroup>
<ItemGroup Condition="'$(IsEQuanticDevMode)' != 'true'">
<PackageReference Include="eQuantic.UI.Primitives" Version="$(EQuanticUIVersion)" />
<PackageReference Include="eQuantic.UI.Code" Version="$(EQuanticUIVersion)" />
<PackageReference Include="eQuantic.UI.Components" Version="$(EQuanticUIVersion)" GeneratePathProperty="true" />
<PackageReference Include="eQuantic.UI.Charts" Version="$(EQuanticUIVersion)" GeneratePathProperty="true" />
<PackageReference Include="eQuantic.UI.Web" Version="$(EQuanticUIVersion)" />
<!-- Der Server trägt die Runtime, die er ausliefert, auch als Datei (tools/runtime/runtime.js). -->
<PackageReference Include="eQuantic.UI.Server" Version="$(EQuanticUIVersion)" GeneratePathProperty="true" />
<!-- dazu das EINE eQuantic.UI.Runtime.{Os}{Arch}-Paket für diese Maschine -->
</ItemGroup>So nennt der Konsument die Version EINMAL, im msbuild-sdks-Eintrag der global.json, den die
Vorlage einstempelt, und die Geschwister folgen. Das native SDK macht dasselbe mit einem
*-*-Rückfall, damit ein Preview-SDK seine eigenen Preview-Geschwister wiederherstellen kann.
Man kann sie überschreiben:
<PropertyGroup>
<EQuanticUIVersion>die-gewuenschte-version</EQuanticUIVersion>
</PropertyGroup>Die Eigenschaft bewegt alle Geschwister zusammen; die Bedingungen oben weisen sie nur zu, wenn sie leer ist.
MeineApp.csproj: <Project Sdk="eQuantic.UI.Sdk">
global.json: { "msbuild-sdks": { "eQuantic.UI.Sdk": "<version>" } }
dotnet restore
↓ Sdk.props: kein Quellbaum daneben → PackageReferences auf $(EQuanticUIVersion)
↓ NuGet installiert die Pakete in den Cache
~/.nuget/packages/equantic.ui.server/<version>/
~/.nuget/packages/equantic.ui.components/<version>/
↓ NuGet erzeugt die $(Pkg*)-Eigenschaften
obj/MeineApp.csproj.nuget.g.props
↓ das SDK löst die Artefakte auf
Sdk.targets nutzt $(PkgeQuantic_UI_Server)/tools/runtime/runtime.js
↓ und führt die Werkzeuge aus, die es ausgeliefert hat
<Sdk-Paket>/tools/net10.0/eqc.dll, eqicon.dll
Ein Build aus dem eigenen Baum des Repositorys (die Beispiele, die Website, ein Scaffold im Test)
geht durch KEIN Paket. Dieselben Sdk.props und Sdk.targets erkennen den Baum neben sich und
schalten auf Projektreferenzen um; es gibt keinen lokalen Feed, keinen Cache zu leeren und keinen
Pack-Schritt zwischen einer Änderung und ihrer Wirkung. dotnet build samples/DefaultUIDashboard ist
die ganze Schleife.
Ein Beispiel importiert die zwei Dateien des SDK direkt:
<!-- samples/DefaultUIDashboard/DefaultUIDashboard.csproj -->
<Project>
<Import Project="../../src/eQuantic.UI.Sdk/Sdk/Sdk.props" />
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<!-- Icon-Packs sind OPT-IN: referenzieren Sie die Sätze, die Sie nutzen. -->
<ItemGroup>
<ProjectReference Include="../../src/eQuantic.UI.Lucide/eQuantic.UI.Lucide.csproj" />
</ItemGroup>
<Import Project="../../src/eQuantic.UI.Sdk/Sdk/Sdk.targets" />
</Project>Sdk.props entscheidet zwischen Paketen und Projekten mit EINER Eigenschaft, und im
Entwicklungsmodus deklariert es zusätzlich die zwei Build-Werkzeuge als Kanten des Build-Graphen:
<!-- Sdk/Sdk.props -->
<IsEQuanticDevMode Condition="Exists('$(_DevRootDir)eQuantic.UI.Primitives/eQuantic.UI.Primitives.csproj')">true</IsEQuanticDevMode>
<ItemGroup Condition="'$(IsEQuanticDevMode)' == 'true'">
<!-- Die BUILD-WERKZEUGE, die dieses Projekt ausführt, als Graphkanten: Nichts linkt gegen sie,
sie müssen nur EXISTIEREN, bevor unsere Targets laufen, und genau das garantiert eine
Kante. -->
<ProjectReference Include="$(_DevRootDir)eQuantic.Build\eQuantic.Build.csproj"
ReferenceOutputAssembly="false" Private="false" SkipGetTargetFrameworkProperties="true"
GlobalPropertiesToRemove="$(_EqToolGlobalsToRemove)" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Native.Build\eQuantic.UI.Native.Build.csproj"
ReferenceOutputAssembly="false" Private="false" SkipGetTargetFrameworkProperties="true"
GlobalPropertiesToRemove="$(_EqToolGlobalsToRemove)" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Primitives\eQuantic.UI.Primitives.csproj" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Code\eQuantic.UI.Code.csproj" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Components\eQuantic.UI.Components.csproj" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Charts\eQuantic.UI.Charts.csproj" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Web\eQuantic.UI.Web.csproj" />
<ProjectReference Include="$(_DevRootDir)eQuantic.UI.Server\eQuantic.UI.Server.csproj" />
<!-- dazu das EINE eQuantic.UI.Runtime.{Os}{Arch}-Projekt, und eQuantic.UI.Generators als Analyzer -->
</ItemGroup>Warum Kanten und keine <MSBuild>-Task inline: Ein Inline-Build führte eine ZWEITE Instanz jedes
Werkzeugprojekts unter eigenen globalen Eigenschaften aus, im Wettlauf mit dem Build der Solution in
dasselbe bin/, und jedes Target, das das Werkzeug ausführte, war durch Exists(eqicon.dll)
abgesichert, das bei einem kalten Build "nein" und beim zweiten "ja" antwortete. Es ging Monate lang
durch, aus dem Zufall, wo die Projekte in der .sln standen. Eine Kante wird von MSBuild selbst
geordnet und serialisiert. Private="false" hält Apphost und json einer exe aus dem bin/ der
Anwendung; GlobalPropertiesToRemove verhindert, dass ein Gerätekopf einem einfachen
net10.0-Werkzeug sein Framework oder seinen Runtime-Identifier mitgibt.
Sdk.targets stellt dann EINE Frage (gibt es einen Quellbaum neben mir?), um zu entscheiden, wo die
beiden Werkzeuge liegen und woher die Artefakte kommen, wenn keine $(Pkg*)-Eigenschaft gesetzt ist:
<!-- Sdk/Sdk.targets -->
<_SdkToolsDir>$(MSBuildThisFileDirectory)../tools/net10.0/</_SdkToolsDir>
<_EqSourceTree Condition="Exists('$(MSBuildThisFileDirectory)../../eQuantic.Build/eQuantic.Build.csproj')">true</_EqSourceTree>
<!-- Ein Quellbaum führt aus, was seine Kanten gerade gebaut haben; ein Paket führt aus, was es
unter tools/ ausgeliefert hat. Ein EqcCliPath, den das Projekt nennt, gewinnt über beide. -->
<EqcCliPath Condition="'$(EqcCliPath)' == '' AND '$(_EqSourceTree)' == 'true'">$(MSBuildThisFileDirectory)../../eQuantic.Build/bin/$(Configuration)/net10.0/eqc.dll</EqcCliPath>
<EqcCliPath Condition="'$(EqcCliPath)' == ''">$(_SdkToolsDir)eqc.dll</EqcCliPath>
<_EqIconToolDir Condition="'$(_EqSourceTree)' == 'true'">$(MSBuildThisFileDirectory)../../eQuantic.UI.Native.Build/bin/$(Configuration)/net10.0/</_EqIconToolDir>
<_EqIconToolDir Condition="'$(_EqIconToolDir)' == ''">$(_SdkToolsDir)</_EqIconToolDir>
<!-- Artefakte: zuerst das $(Pkg*) des Pakets, sonst der Baum neben dem SDK -->
<_StandardComponentsDir Condition="'$(_StandardComponentsDir)' == '' And Exists('$(_DevComponentsDir)')">$(_DevComponentsDir)</_StandardComponentsDir>
<_RuntimeSourcePath Condition="'$(_RuntimeSourcePath)' == '' And Exists('$(MSBuildThisFileDirectory)../../eQuantic.UI.Server/wwwroot/runtime.js')">$(MSBuildThisFileDirectory)../../eQuantic.UI.Server/wwwroot/runtime.js</_RuntimeSourcePath>
<BunZipPath Condition="'$(BunZipPath)' == '' and Exists('$(MSBuildThisFileDirectory)../../$(BunRuntimePackageId)/tools/bun/$(_BunZipName)')">$(MSBuildThisFileDirectory)../../$(BunRuntimePackageId)/tools/bun/$(_BunZipName)</BunZipPath>Ein Werkzeug, das ohnehin fehlt, scheitert mit seinem Namen, bevor irgendetwas läuft: EQ4002 für
eqc, EQ4001 für eqicon: ein kaputter Graph in einem Quellbaum, ein kaputtes Paket aus NuGet, ein
falscher Pfad unter einem ausdrücklichen EqcCliPath. Keiner davon lässt sich dadurch beheben, dass
man zweimal baut. Siehe Diagnose.
Das Verzeichnis artifacts/packages, das die nuget.config des Repositorys noch als lokale Quelle
deklariert, ist NICHT Teil dieses Ablaufs: Nichts in einem Build aus dem Quellbaum schreibt dorthin
oder liest daraus. Um eine Änderung über den ECHTEN Konsumentenweg zu prüfen (Pakete, global.json,
Restore), nutzen Sie das Rezept für den lokalen Feed in
Build-Ablauf.
Vorteile:
- Wer das Framework entwickelt, arbeitet direkt mit dem Quellcode; eine Änderung ist beim nächsten
dotnet buildsichtbar - Kein Pack, kein Restore, kein Cache-Schritt zwischen einer Änderung und dem Beispiel, das sie zeigt
- Dieselben
Sdk.propsundSdk.targetsfunktionieren in beiden Szenarien: Der Konsumentenweg ist nie ein anderer Codeweg, nur eine andere Antwort auf "gibt es einen Baum neben mir?"
-
Lassen Sie jedes Paket seine eigenen Artefakte verwalten
- Server paketiert die runtime.js, die es ausliefert
- Components paketiert Quelldateien
-
Referenzieren Sie über NuGet-Eigenschaften
- Nutzen Sie
$(PkgeQuantic_UI_*)statt hart verdrahteter Pfade
- Nutzen Sie
-
Sehen Sie Rückfälle für die Entwicklung vor
- Erlauben Sie dem SDK, die Artefakte im Quellbaum zu finden, wenn das Framework entwickelt wird
-
Scheitern Sie mit Namen
- Ein fehlendes Werkzeug oder Artefakt ist ein Fehler, der sagt, welches Paket oder welche Kante fehlt, nie eine Warnung und ein Build, der ohne JavaScript weiterläuft
-
Betten Sie keine Artefakte anderer Pakete ein
- Das SDK sollte die runtime.js des Servers NICHT in sich kopieren
-
Nutzen Sie keine relativen Pfade über Pakete hinweg
- Schlecht:
$(MSBuildThisFileDirectory)../../../Server/tools/runtime/ - Gut:
$(PkgeQuantic_UI_Server)/tools/runtime/
- Schlecht:
-
Legen Sie kein Werkzeug von Hand neben das SDK
- Eine Kopie, die ein früherer Build dort gelassen hat, ist von Bauart veraltet; das SDK führt aus, was seine Kanten gerade gebaut haben, oder was das Paket ausgeliefert hat
-
Erzeugen Sie keine zyklischen Abhängigkeiten
- Pakete sollten einen klaren Abhängigkeitsgraphen haben
Error: eQuantic.UI: the served runtime was not found. It ships inside the eQuantic.UI.Server package (version …) at tools/runtime/runtime.js; try 'dotnet restore --force'.
Ursache: $(PkgeQuantic_UI_Server) ist leer, und es gibt neben dem SDK keinen Quellbaum, dessen
Server-Projekt wwwroot/runtime.js geschrieben hat (diese Datei ist die Build-Ausgabe des Servers)
Behebung:
dotnet restore --force
# Prüfen, ob das Server-Paket die Runtime trägt
ls ~/.nuget/packages/equantic.ui.server/<version>/tools/runtime/Error: eQuantic.UI: Standard components not found. Ensure the eQuantic.UI.Components package (version …) is installed.
Ursache: $(PkgeQuantic_UI_Components) ist leer und es gibt neben dem SDK keinen Quellbaum
Behebung:
dotnet restore --force
# Prüfen, ob das Components-Paket Quelldateien hat
ls ~/.nuget/packages/equantic.ui.components/<version>/tools/source/error EQ4002: The eQuantic compiler (eqc) is missing at '…/tools/net10.0/eqc.dll'. …
Ursache: In einem Quellbaum hat das Projekt des Werkzeugs nicht vor diesem gebaut (ein kaputter
Build-Graph, lesen Sie die Fehler ÜBER diesem); aus einem Paket ist das Paket ohne tools/net10.0/
ausgeliefert worden; mit einem ausdrücklichen EqcCliPath nennt der Pfad eine Datei, die nicht da
ist
Behebung: Keiner davon lässt sich dadurch beheben, dass man zweimal baut. Reparieren Sie den Graphen, leeren Sie die eQuantic-Pakete aus dem Cache und stellen Sie neu wieder her, oder korrigieren Sie den Pfad. Siehe Diagnose
Symptom: Der Build nutzt eine alte runtime.js trotz eines neuen Server-Pakets
Ursache: Der NuGet-Cache wurde nicht geleert
Behebung:
# Dieses eine Paket aus dem Cache leeren
rm -rf ~/.nuget/packages/equantic.ui.server/<version>
# Restore erzwingen
dotnet restore --force --no-cacheAus dem Framework-Checkout entfernt dotnet msbuild -t:ClearEQuanticCache alle equantic.*-Pakete
auf einmal aus dem Cache.
- Build-Ablauf - die vollständige Build-Pipeline, und das Rezept für den lokalen Feed
- Runtime - die Architektur der Runtime und ihre Verteilung
- Compiler - wie der Compiler von C# nach JS arbeitet
- Diagnose - jedes EQxxxx, das SDK und Compiler melden
🏁 Hier starten
🏗️ Architektur
- Architekturüberblick
- Write-once-Komponenten
- Deklarative Oberfläche
- Paketarchitektur
- Komponenten
- Styling
- Lokalisierung
- Analytics und GTM
📱 Write-once
- Photon-Engine
- Design System
- Fähigkeiten
- Speicher
- Formulare
- Code-Editor
- Markdown
- Mermaid
- E-Mail-Rendering
⚙️ Kompilierung
⚡ Runtime
🔌 Server
🎨 Ökosystem
🚀 Entwicklung