Nx ist ein leistungsstarkes Build-System fuer Monorepos, das intelligentes Caching, Task-Orchestrierung und Code-Generatoren bietet. Es macht die Verwaltung mehrerer Projekte in einem Repository schnell, skalierbar und entwicklerfreundlich.

Was sind Monorepos? πŸ€”

Stell dir vor, du hast mehrere Projekte, eine Angular-App, ein NestJS-Backend, ein paar Shared Libraries, und alles lebt in einem einzigen Git-Repository. Das ist ein Monorepo. Statt fuer jedes Projekt ein eigenes Repo zu pflegen (Polyrepo), teilen sich alle Projekte die gleiche Codebasis, die gleichen Dependencies und die gleichen CI/CD-Pipelines.

Klingt erstmal chaotisch? Genau hier kommt Nx ins Spiel.

Nx als Build-System πŸ—οΈ

Nx ist kein Framework, es ist ein Build-System und Monorepo-Management-Tool. Es kuemmert sich darum, dass nur das gebaut, getestet und gelintet wird, was sich tatsaechlich geaendert hat. Dabei unterstuetzt Nx nicht nur Angular, sondern auch React, NestJS, Node.js, und viele weitere Technologien.

Die Kernfeatures von Nx sind:

  • Intelligentes Caching, Aufgaben werden nur einmal ausgefuehrt und dann gecacht
  • Task-Orchestrierung, Nx weiss, welche Tasks parallel laufen koennen
  • Code-Generatoren, Boilerplate-Code wird automatisch erstellt
  • Affected Commands, Nur geaenderte Projekte werden verarbeitet
Nx β€” Smart Monorepos Β· Fast Builds
Nx is a build system and monorepo management tool that enables fast, scalable development with smart caching and task orchestration.

Workspace einrichten πŸš€

Ein neuer Nx-Workspace ist schnell erstellt. Du brauchst nur Node.js und npm:

# Neuen Nx-Workspace erstellen
npx create-nx-workspace@latest mein-monorepo

# Dabei wirst du gefragt:
# - Welches Preset? (angular, react, nest, etc.)
# - Standalone oder integriert?
# - CI-Setup?

Nach der Installation hast du eine Ordnerstruktur, die ungefaehr so aussieht:

mein-monorepo/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ frontend/        # Angular App
β”‚   └── backend/         # NestJS API
β”œβ”€β”€ libs/
β”‚   β”œβ”€β”€ shared/          # Geteilte Bibliotheken
β”‚   └── ui/              # UI-Komponenten
β”œβ”€β”€ nx.json              # Nx-Konfiguration
β”œβ”€β”€ package.json
└── tsconfig.base.json

Generatoren: Code auf Knopfdruck 🧩

Generatoren sind eines der maechtigsten Features von Nx. Statt manuell Dateien und Konfigurationen anzulegen, generiert Nx alles fuer dich:

# Neue Angular-App erstellen
npx nx generate @nx/angular:application --name=dashboard --directory=apps/dashboard

# Neue Shared Library erstellen
npx nx generate @nx/js:library --name=utils --directory=libs/shared/utils

# Neue NestJS-API erstellen
npx nx generate @nx/nest:application --name=api --directory=apps/api

# Angular-Komponente in einer Library
npx nx generate @nx/angular:component --name=button --project=ui

Jedes generierte Projekt bekommt automatisch eine project.json, die alle verfuegbaren Targets definiert:

{
  "name": "dashboard",
  "sourceRoot": "apps/dashboard/src",
  "projectType": "application",
  "targets": {
    "build": {
      "executor": "@angular-devkit/build-angular:browser",
      "options": {
        "outputPath": "dist/apps/dashboard"
      }
    },
    "serve": {
      "executor": "@angular-devkit/build-angular:dev-server"
    },
    "test": {
      "executor": "@nx/jest:jest",
      "options": {
        "jestConfig": "apps/dashboard/jest.config.ts"
      }
    },
    "lint": {
      "executor": "@nx/eslint:lint"
    }
  }
}
Angular Signals: Reaktives State-Management ohne RxJS πŸš€
Angular Signals bieten eine einfachere Alternative zu RxJS fΓΌr reaktives State Management.

Executors: Tasks definieren und ausfuehren βš™οΈ

Executors sind das Gegenstueck zu Generatoren, sie fuehren Tasks wie Build, Test oder Lint aus. Nx bringt viele Executors mit, aber du kannst auch eigene schreiben:

# App bauen
npx nx build dashboard

# App starten
npx nx serve dashboard

# Tests laufen lassen
npx nx test dashboard

# Lint ausfuehren
npx nx lint dashboard

# Mehrere Tasks gleichzeitig
npx nx run-many --target=build --projects=dashboard,api

Caching: Nie wieder doppelt bauen πŸ’¨

Das Caching von Nx ist ein absoluter Gamechanger. Wenn du ein Projekt baust und sich danach nichts aendert, liefert Nx beim naechsten Build das Ergebnis direkt aus dem Cache, in Millisekunden statt Minuten.

# Erster Build - dauert z.B. 45 Sekunden
npx nx build dashboard
# Output: "Successfully built dashboard (45s)"

# Zweiter Build - aus dem Cache
npx nx build dashboard
# Output: "Nx read the output from the cache (42ms)"

Nx cached dabei nicht nur den Build-Output, sondern auch Test-Ergebnisse und Lint-Checks. Die Cache-Konfiguration kannst du in der nx.json anpassen:

{
  "targetDefaults": {
    "build": {
      "cache": true,
      "dependsOn": ["^build"],
      "inputs": ["production", "^production"]
    },
    "test": {
      "cache": true,
      "inputs": ["default", "^production"]
    },
    "lint": {
      "cache": true,
      "inputs": ["default"]
    }
  }
}

Affected Commands: Nur das Noetige tun 🎯

In einem grossen Monorepo willst du nicht bei jeder kleinen Aenderung alles neu bauen. Nx analysiert den Abhaengigkeitsgraph und fuehrt Tasks nur fuer betroffene Projekte aus:

# Nur geaenderte Projekte bauen
npx nx affected --target=build

# Nur geaenderte Projekte testen
npx nx affected --target=test

# Nur geaenderte Projekte linten
npx nx affected --target=lint

# Graph der betroffenen Projekte anzeigen
npx nx affected:graph

Wenn du zum Beispiel nur eine Shared Library aenderst, erkennt Nx automatisch, welche Apps diese Library nutzen und baut nur diese neu. Das spart in der CI/CD-Pipeline enorm viel Zeit.

Shared Libraries: Code teilen wie ein Profi πŸ“š

Der groesste Vorteil eines Monorepos ist das einfache Teilen von Code. In Nx erstellst du dafuer Libraries:

// libs/shared/utils/src/lib/format-date.ts
export function formatDate(date: Date): string {
  return date.toLocaleDateString('de-DE', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });
}

// libs/shared/types/src/lib/user.interface.ts
export interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
}

Diese Libraries kannst du dann in jeder App importieren, ohne sie separat zu publishen:

// apps/dashboard/src/app/app.component.ts
import { formatDate } from '@mein-monorepo/shared/utils';
import { User } from '@mein-monorepo/shared/types';

// Kein npm install noetig - alles im selben Repo!

Die Pfad-Aliase werden automatisch in der tsconfig.base.json konfiguriert:

{
  "compilerOptions": {
    "paths": {
      "@mein-monorepo/shared/utils": ["libs/shared/utils/src/index.ts"],
      "@mein-monorepo/shared/types": ["libs/shared/types/src/index.ts"],
      "@mein-monorepo/ui": ["libs/ui/src/index.ts"]
    }
  }
}
NPM: Der Paketmanager fΓΌr dein Projekt πŸͺ„
NPM ist der Standard-Paketmanager fΓΌr Node.js und JavaScript-Projekte.

Nx Cloud: Verteiltes Caching ☁️

Lokales Caching ist super, aber was ist mit deinem Team? Wenn dein Kollege das Projekt schon gebaut hat, warum solltest du es nochmal bauen muessen? Genau dafuer gibt es Nx Cloud.

# Nx Cloud aktivieren
npx nx connect

# Danach wird der Cache automatisch geteilt
# Wenn ein Teammitglied baut, profitieren alle anderen

Nx Cloud bietet:

  • Remote Caching, Cache wird teamweit geteilt
  • Distributed Task Execution (DTE), Tasks werden auf mehrere CI-Agents verteilt
  • CI-Dashboard, Uebersicht ueber alle Builds und deren Performance

Besonders in der CI/CD-Pipeline mit GitHub Actions macht Nx Cloud einen riesigen Unterschied:

GitHub Actions: CI/CD fΓΌr deine Projekte πŸ”„
GitHub Actions automatisiert deine CI/CD-Pipeline direkt in deinem Repository.

Monorepo vs. Polyrepo: Wann was? 🀷

Nicht jedes Projekt braucht ein Monorepo. Hier eine GegenueberΒ­stellung:

Kriterium Monorepo Polyrepo
Code-Sharing Einfach ueber Libraries Ueber npm-Pakete
Abhaengigkeiten Eine package.json Pro Projekt eigene
CI/CD Zentral, mit Affected Pro Repo separat
Teamgroesse Gut ab 2+ Projekte Gut fuer unabhaengige Teams
Onboarding Ein Repo klonen Mehrere Repos klonen
Versionierung Alles synchron Unabhaengig

Monorepo passt gut, wenn:

  • Du mehrere zusammenhaengende Projekte hast (z.B. Frontend + Backend + Shared Libs)
  • Dein Team gemeinsam an der Codebasis arbeitet
  • Du Code zwischen Projekten teilen willst
  • Du konsistente Tooling- und Dependency-Versionen brauchst

Polyrepo passt besser, wenn:

  • Projekte voellig unabhaengig voneinander sind
  • Verschiedene Teams unterschiedliche Release-Zyklen haben
  • Die Projekte unterschiedliche Tech-Stacks nutzen

Praxis-Tipps fuer den Einstieg πŸ’‘

  1. Klein anfangen, Starte mit einer App und ein bis zwei Libraries
  2. Grenzen definieren, Nutze Nx Module Boundaries, um Abhaengigkeitsregeln durchzusetzen
  3. Nx Console nutzen, Die VS Code Extension macht vieles einfacher
  4. Dependency Graph ansehen, npx nx graph visualisiert deine Projektstruktur
  5. Caching von Anfang an, Aktiviere Nx Cloud frueh, damit dein Team sofort profitiert
# Dependency Graph oeffnen
npx nx graph

# Module Boundaries pruefen
npx nx lint --all

Fazit 🎬

Nx macht Monorepos nicht nur machbar, sondern richtig angenehm. Intelligentes Caching, Code-Generatoren und Affected Commands sparen dir taeglich Zeit. Wenn du mehrere zusammenhaengende Projekte hast, ist ein Nx-Monorepo definitiv einen Blick wert.