W9 hat eine Anwendung gebaut: kladde-angular, ein Projekt in einem Ordner. Dieser Kurs fragt, was passiert, wenn es zwei Anwendungen werden (die Büro-Anwendung und die öffentliche Buchung), mehrere Fachgebiete (Kontakte, Termine, Ausschreibungen) und mehr als ein Team. Die Lektion klärt zuerst, wann ein Monorepo die Antwort ist, legt dann den Workspace kladde-workspace mit Nx an und zieht die SPA aus W9 als kladde-buero hinein. Regeln zwischen Bibliotheken folgen in Lektion 0102, der Cache in 0103. Voraussetzung ist W9; Entscheidungen schreiben wir als ADR auf, wie in K4 Lektion 4.1.3 gelernt.

Stand der Prüfung. Ausgeführt wurde alles, was hier mit Ergebnis steht, in einem Wegwerf-Workspace außerhalb des Repositorys: Node 24.22.3, npm 11.7.0, Nx 24.0.6 (nx, @nx/angular), Angular 22.2 (@angular/core 22.2.6), TypeScript 6.0.3, Vitest 4.1.12; nx build, nx test, nx lint und nx graph --file endeten mit Exit 0. Die „SPA aus W9“ ist dabei die Referenzanwendung des Schreibens (ein frisches ng new-Projekt mit Routing und SCSS, zwei Tests), nicht Ihre fertige Kladde-SPA. Nicht ausgeführt: nx init und nx import (für bestehende Repositorys), nx graph im Browser, ng serve im Workspace. Nx' Aussagen stammen von den Seiten zu Cache, Affected und Modulgrenzen (gelesen, siehe Weiterlesen); die Gründe gegen ein Monorepo sind unser Urteil, keine Quelle. Ein Versuch mit --preset=angular-monorepo lieferte bei uns, in einer Umgebung mit Variablen eines KI-Agenten, eine Vorlage mit Beispielanwendungen shop und api; ob das bei Ihnen auch so ist, ist offen. Wir nehmen das Preset apps.

Was ein Monorepo löst und was es kostet

Ein Monorepo ist ein Repository mit mehreren Projekten (Anwendungen und Bibliotheken), die einander kennen dürfen. Es ist kein Ziel, sondern ein Werkzeug: Code, der zusammen geändert wird, liegt in einem Commit und einer Prüfung.

Was es löst Was es kostet
Eine Änderung an einer geteilten Bibliothek und ihren Nutzern ist ein Pull Request, keine Versionssprünge zwischen Repositorys. Das Repository wächst: Klonen, Suchen, Verlauf. Eine Größe, ab der es zu groß ist, nennen wir nicht.
Eine Version von Angular und RxJS für alle; Upgrades passieren einmal. Alle sind an dieselbe Angular-Fassung gebunden; eine Anwendung, die zurückbleiben muss, bremst den Rest.
Lint, Format und Grenzen an einer Stelle; Wiederverwendung ohne Veröffentlichung. Ohne Regeln wächst ein Knäuel: Jedes Projekt darf alles importieren (Lektion 0102).
Ein Werkzeug sieht den ganzen Graphen und baut nur, was betroffen ist. Die CI braucht dieses Werkzeug und die ganze Git-Historie (Lektion 0103).

Dazu kommen Zugriffsrechte (wer das Repository sieht, sieht alles), Besitz (ein Team, dem sein Ordner gehört, braucht Regeln wie CODEOWNERS) und Veröffentlichung mehrerer Pakete mit eigenen Versionen (Lektion 0302). Für die Kladde gilt: Zwei Anwendungen teilen Kontakt- und Terminformen, Bausteine und Hilfsfunktionen, und ein Team ändert sie gemeinsam. Da trägt ein Monorepo. Bei zwei Teams mit eigenen Zeitplänen und Angular-Fassungen ginge die Frage anders aus; Lektion 0303 behandelt das Gegenstück, die Micro-Frontends.

Nx im Überblick

Nx ist ein Werkzeug für Monorepos (nx und @nx/angular 24.0.6, MIT-Lizenz laut npm-Registry). Vier Bausteine:

  • Projekte und Projektgraph. Jede Anwendung und Bibliothek ist ein Projekt mit Name, Ordner, Etiketten und Aufgaben. Aus den Importen errechnet Nx den Graphen: wer von wem abhängt.
  • Aufgaben (Targets). build, test, lint, serve. nx build kladde-buero führt eine aus, nx run-many -t lint test build alle für alle Projekte.
  • Cache. Vor einer Aufgabe bildet Nx aus ihren Eingaben einen Hash; gibt es das Ergebnis schon, wird es wiederhergestellt (Lektion 0103).
  • Generatoren. nx generate legt Anwendungen, Bibliotheken und Komponenten nach einer Vorlage an und trägt sie in die Konfiguration ein.

Angular-CLI-Workspace oder Nx? Auch die Angular CLI kennt Workspaces mit mehreren Projekten. Nx setzt auf denselben Bausteinen auf: Die Aufgabe build unserer Anwendung ruft den Builder @angular/build:application auf, denselben wie ng build in W9. Nx fügt Graph, Cache, affected, Grenzregeln und Generatoren für Bibliotheken hinzu. Wer eine Anwendung hat, braucht das nicht. Ob ng im Nx-Workspace weiterläuft, haben wir nicht geprüft; der Kurs benutzt nx.

Den Workspace anlegen

Prüfen Sie zuerst die Fassung; Angular 22 verlangt Node ^22.22.3, ^24.15.0 oder ^26.0.0 (angular.dev, „Versions“). Der Kurs nennt die Linie 24.

PowerShell
node --version
npx create-nx-workspace@24.0.6 kladde-workspace --preset=apps --nxCloud=skip `
    --aiAgents=none --analytics=false --interactive=false --defaultBase=master `
    --formatter=prettier --linter=eslint

--nxCloud=skip verzichtet auf den entfernten Cache (Lektion 0103), --defaultBase=master nennt den Hauptzweig, gegen den affected vergleicht (bei Ihnen vielleicht main). Es entsteht ein leerer Workspace mit npm-Workspaces: nx.json, package.json, noch kein Angular. Nx liest den Verlauf, also initialisieren Sie Git, dann folgen Angular-Unterstützung und Anwendung:

PowerShell
cd kladde-workspace
git init -b master
git add -A
git commit -m "chore: initial workspace"
npx nx add @nx/angular
npx nx generate @nx/angular:application apps/kladde-buero --name=kladde-buero `
    --prefix=kl --style=scss --e2eTestRunner=none --linter=eslint --no-interactive

nx add meldete bei uns „Package @nx/angular added successfully“; prüfen Sie, dass @nx/angular in den devDependencies steht (nachtragen: npm install -D @nx/angular@24.0.6). Präfix kl und SCSS sind die Festlegungen des Kurses wie in W9; Standard für --e2eTestRunner ist laut Hilfe des Generators Playwright, ein E2E-Projekt brauchen wir hier nicht. Der Generator schreibt apps/kladde-buero/project.json, die tsconfig-Dateien, src/ mit main.ts, app.config.ts, app.routes.ts, app.ts und ergänzt nx.json und eslint.config.mjs. Als Testläufer trägt er Vitest ein (@angular/build:unit-test, wie ng test in W9).

PowerShell
npx nx build kladde-buero
npx nx test kladde-buero
npx nx lint kladde-buero

Bei uns: build Exit 0, Ausgabe in dist/apps/kladde-buero, mit einer Warnung zum Stil-Budget von nx-welcome.ts (Willkommensseite der Vorlage, sie fällt gleich weg); test „Test Files 1 passed, Tests 2 passed“ und „Cache: 0/1 hit (0%)“; lint ohne Befund.

Die Konfiguration

project.json beschreibt ein Projekt (gekürzt):

JSON
{
  "name": "kladde-buero",
  "projectType": "application",
  "prefix": "kl",
  "sourceRoot": "apps/kladde-buero/src",
  "tags": [],
  "targets": {
    "build": {
      "executor": "@angular/build:application",
      "outputs": ["{options.outputPath}"],
      "options": { "outputPath": "dist/apps/kladde-buero" }
    },
    "test": { "executor": "@angular/build:unit-test", "options": { "watch": false } }
  }
}

outputs nennt die Dateien, die der Cache wiederherstellt. Die tags sind noch leer; ihr Zweck folgt in Lektion 0102.

nx.json gilt für den Workspace; drei Abschnitte hat der Generator gefüllt:

  • namedInputs legt fest, welche Dateien Eingaben einer Aufgabe sind: default (alles im Projekt plus gemeinsame Dateien) und production (ohne Testdateien und Lint-Konfiguration). Ein Build, der production liest, läuft nicht neu, wenn nur ein Test sich ändert.
  • targetDefaults gibt allen Aufgaben eines Builders gemeinsame Werte. Für @angular/build:application stehen cache: true, dependsOn: ["^build"] (erst die build-Aufgaben der Projekte, von denen dieses abhängt) und inputs: ["production", "^production"].
  • plugins (hier @nx/eslint/plugin) leiten Aufgaben aus Konfigurationsdateien ab: Eine Bibliothek braucht kein lint in ihrer project.json. nx show project <name> zeigt alle Aufgaben, die Nx sieht.

Zu strict: Die Vorlage setzt in tsconfig.base.json "strict": false, in den tsconfig.json von Anwendung und Bibliotheken aber true. Unsere Regel ist strenges TypeScript überall: Setzen Sie es an der Wurzel auf true. In unserem Workspace mit sechs Projekten (so wie er nach Lektion 0102 aussieht) lief danach alles weiter mit Exit 0, und keine der 13 Aufgaben kam aus dem Cache: Die Wurzelkonfiguration ist Eingabe aller Aufgaben.

Die SPA aus W9 hineinziehen

Die Anwendung der Vorlage ist nur ein Gerüst; der Inhalt ist die SPA aus W9. Kopieren ist der kurze Weg, den wir gegangen sind (Quelle web/kladde-angular, Ziel apps/kladde-buero):

PowerShell
Remove-Item -Recurse -Force apps\kladde-buero\src\app
Copy-Item ..\kladde-angular\src\app apps\kladde-buero\src\app -Recurse
Copy-Item ..\kladde-angular\src\main.ts apps\kladde-buero\src\main.ts -Force
Copy-Item ..\kladde-angular\src\styles.scss apps\kladde-buero\src\styles.scss -Force

nx import kann ein ganzes Repository samt Verlauf holen; ausgeführt haben wir es nicht, die Seite dazu nicht gelesen: offen. Danach drei Anpassungen von Hand: Selektor in app.ts und in den Tests heißen kl-root (die Referenzanwendung hatte app-root), der Name in Titel und Test lautet kladde-buero, und zusätzliche Abhängigkeiten (MSAL aus W9 0301, ein OpenAPI-Client) kommen in die package.json an der Wurzel: ein Nx-Workspace hat eine Version jedes Pakets für alle Projekte. Der Proxy proxy.conf.json (W9 0101) gehört in apps/kladde-buero und in die Aufgabe serve; das haben wir nicht ausgeführt.

Bei uns bauten und testeten die Läufe danach wieder mit Exit 0: build mit einem Hauptbündel von etwa 217 kB (Rohgröße, nur ein Beleg, kein Maßstab), test 2 von 2, lint ohne Befund. Ab jetzt heißt die Büro-Anwendung kladde-buero; kladde-angular bleibt als Vorlage, bis der Workspace dieselben Seiten zeigt.

Der Projektgraph

PowerShell
npx nx graph --file=graph.json
npx nx show projects

nx graph ohne Argument öffnet den gezeichneten Graphen im Browser (nicht ausgeführt); mit --file entsteht JSON mit nodes und dependencies. Mit einer Anwendung ist der Graph ein einzelner Knoten; die ersten Kanten entstehen in Lektion 0102.

Übung 1

Workspace anlegen, SPA hineinziehen, Entscheidung festhalten.

  1. Prüfen Sie node --version, legen Sie kladde-workspace mit dem Preset apps an, initialisieren Sie Git, fügen Sie @nx/angular hinzu und erzeugen Sie kladde-buero mit Präfix kl und SCSS. Setzen Sie strict in tsconfig.base.json auf true.
  2. Ersetzen Sie den Quelltext der Anwendung durch den Ihrer W9-SPA, passen Sie Selektor und Titel an, verschieben Sie zusätzliche Abhängigkeiten in die Wurzel-package.json.
  3. Führen Sie nx build kladde-buero, nx test kladde-buero und nx lint kladde-buero aus (jeweils Exit-Code lesen) und geben Sie den Graphen mit nx graph --file=graph.json aus.
  4. Schreiben Sie docs/adr/0001-monorepo.md nach K4 4.1.3: Kontext, Entscheidung (Nx-Monorepo), Folgen und eine Alternative mit Grund.

So prüfen Sie: Alle Läufe enden mit exit=0, graph.json enthält den Knoten kladde-buero, im ADR nennen die Folgen mindestens einen Nachteil, nicht nur Vorteile.

Lösung 1

  • create-nx-workspace fragt nach Dingen: Mit --interactive=false und allen Optionen aus dem Text fragt es nicht; --nxCloud=skip beantwortet die Frage zu Nx Cloud.
  • Der Generator meldet, @nx/angular fehle: npm install -D @nx/angular@24.0.6.
  • npm druckt „Unsupported engine“: Etwas in der Kette läuft mit einer anderen Node-Fassung als gedacht. Bei uns lief npm mit Node 22.12.0 und druckte diese Hinweise, nx lief unter 24.22.3; prüfen Sie, mit welchem Node jedes Werkzeug startet.
  • Die Tests der SPA finden app-root nicht oder den alten Titel: Selektor und Titel in app.ts und app.spec.ts anpassen. Ein fehlendes Paket (MSAL, ein Client) gehört in die Wurzel-package.json.
  • Ein ADR-Beispiel: „Die öffentliche Buchung (kladde-buchung) braucht dieselben Kontaktformen und Bausteine wie das Büro. Wir nehmen ein Monorepo mit Nx. Folge: eine Angular-Fassung; ohne Grenzregeln droht ein Knäuel. Verworfen: zwei Repositorys mit einem veröffentlichten Paket, weil jede Änderung an den Formen zwei Pull Requests und eine Version bedeutet.“

Was Sie jetzt können

  • Sie sagen, was ein Monorepo löst und kostet, und begründen für die Kladde, warum es trägt.
  • Sie benennen Projektgraph, Aufgaben, Cache und Generatoren und lesen nx.json (namedInputs, targetDefaults, plugins) und project.json.
  • Sie legen einen Nx-Workspace mit Angular-Anwendung an und prüfen ihn mit build, test und lint samt Exit-Code.
  • Sie ziehen die SPA aus W9 als kladde-buero hinein und halten die Entscheidung als ADR fest.

Weiterlesen

Die Kladde: Der Workspace kladde-workspace steht, kladde-buero baut, testet und prüft. Als Nächstes folgt Lektion 0102: Bibliotheken nach Art und Fachgebiet, Etiketten und ein Lint-Lauf, der einen verbotenen Import ablehnt.