Effiziente Monorepos mit Nx

19 Jan. 2026

6 Minuten Lesezeit

Nx ist eine Open‑Source Build‑Plattform speziell für Monorepositories mit dem Anspruch, den gesamten Entwicklungszyklus spürbar zu erleichtern. Nx wird vor allem in großen JavaScript/TypeScript-Projekten genutzt, die als Monorepositories organisiert sind und viele gemeinsam genutzte Bibliotheken enthalten.

Nx beschleunigt die Entwicklung von Monorepositories durch:

  • Affected‑Analyse: baut und testet nur tatsächlich von Änderungen betroffene Projekte inklusive ihrer Abhängigkeiten

  • Intelligenter Task‑Runner: bestimmt die korrekte Ausführungsreihenfolge von Tasks im Nx‑Monorepository

  • Deterministisches Caching: Ergebnisse werden bei unveränderten Inputs wiederverwendet

  • Erweiterbar durch Plugins: so lassen sich Tools wie Vite, ESLint oder Vitest integrieren

Im Folgenden wird erläutert, wie Nx diese Beschleunigung erreicht und welche Features die Arbeit mit einem Monorepository deutlich vereinfachen.

Der Projektgraph: Grundlage für Affected-Analyse und Task-Ausführung

Das Herzstück von Nx ist der Projektgraph: Aus den package.json-Dateien und dem Quellcode leitet Nx ab, welche Projekte in einem Monorespository existieren, wie sie voneinander abhängen und welche Projekte in welcher Reihenfolge gebaut werden müssen.

Über den Projektgraphen kann Nx auch nachvollziehen auf welche Projekte eine Änderung Auswirkungen hat. Den Projektgraphen kann man sich mit dem Befehl nx graph visualisieren lassen. Im Folgenden ist der Projektgraph des Open-Source-Projektes Onion-Initializr zu sehen:

Visualisierung eines Nx‑Projektgraphen
Visualisierung eines Nx‑Projektgraphen

Der Projektgraph zeigt alle Projekte im Workspace als Knoten sowie deren Abhängigkeiten als Kanten. So lässt sich die Struktur eines Monorepository schnell erfassen, Kopplungen werden sichtbar und der Einstieg sowie die Orientierung in großen Workspaces werden deutlich erleichtert. Auch die Einhaltung von Architekturregeln wird damit unterstützt: Wenn ein lib-Modul etwa direkt auf das cli‑Paket zugreift, lässt sich diese unerwünschte Kopplung im Graph schnell erkennen.

Für die automatische Durchsetzung sorgt ergänzend die Regel „enforce-module-boundaries“ des ESLint-Plugins, mit dieser lassen sich Imports verbieten und so Architekturgrenzen durchsetzen. Darüber hinaus prüft die Regel „dependency‑checks“, ob alle im Code verwendeten externen Pakete auch korrekt in der package.json deklariert sind. Das ESLint-Plugin ist eines von vielen Plugins, die für Nx bereitgestellt werden. Wie Plugins in Nx verwendet werden und welche Plugins installiert werden können, wird später erklärt.

Task-Runner

Ein Task in Nx bezeichnet die Ausführung eines Skripts in einem Projekt. Dieses kann aus unterschiedlichen Quellen stammen, etwa aus einem Plugin oder der Nx-Konfiguration. Auch die Skripte, welche in der package.json definiert sind, erkennt Nx automatisch als Tasks.

Mit dem Befehl

pnpm nx show project <projectName>

kann man sich die zur Verfügung stehenden Tasks eines Nx-Projektes ansehen. Per IDE-Plugin kann man sich die Task-Liste auch direkt in der IDE anzeigen lassen und man kann die Tasks direkt per Klick ausführen.

In einem Monorepository möchte man Tasks typischerweise in mehreren Projekten im Monorepository ausführen und nicht nur in einem Paket. Etwa wenn eine Änderung Auswirkungen auf mehrere Projekte hat. Es ist zudem auch möglich, über das Monorepository hinweg alle Tasks aller Pakete mit einem bestimmten Namen auszuführen. Der folgende Befehl führt alle verfügbaren Skripte in allen Paketen aus, die als Target build haben, also build heißen:

pnpm nx run-many -t build

Ebenso können Befehle auf bestimmte Pakete begrenzt und aus dem Root aufgerufen werden. Hier werden nur die Pakete cli und lib gebaut:

pnpm nx run-many -t build cli lib

Nur geänderte Projekte bauen

Im Gegensatz dazu werden Befehle mit affected nur in Paketen ausgeführt, die von Änderungen betroffen sind. Nx affected nutzt die Git-Historie, um nur wirklich betroffene Projekte zu bauen und zu testen. Konkret vergleicht Nx per git diff zwei Referenzen (base und head) und ordnet die gefundenen Änderungen den Projekten im Workspace zu. Nx ermittelt daraus nur für die betroffenen Projekte die Tasks für das gewünschte Target (z. B. build) und führt sie in der richtigen Reihenfolge aus.

pnpm nx affected -t build

Änderungen betreffen oft nicht nur das direkt angepasste Projekt, sondern auch abhängige Pakete. Tasks können aufeinander aufbauen. Über das Feld dependsOn in der Projektkonfiguration lassen sich Abhängigkeiten zwischen Tasks definieren. So kann Nx zum Beispiel beim Bauen einer App automatisch zuerst die benötigten Pakete bauen ("dependsOn": ["^build"]). Dadurch laufen Tasks immer in der richtigen Reihenfolge, ohne dass man sie manuell koordinieren muss.

Zusätzlich spart das deterministische Nx-Caching weitere Tasks ein, wenn relevante Inputs gleich sind.

Caching

Nx Caching beschleunigt die Taskausführung, indem es die Ergebnisse vorheriger Ausführungen wiederverwendet, wenn sich die relevanten Eingaben nicht geändert haben. Dazu bildet Nx einen Hash aus allen Einflussfaktoren (Quellcode, Konfiguration, Abhängigkeiten) und speichert die Artefakte lokal. Artefakte aus Builds, Tests usw. werden nur dann neu erstellt, wenn sich relevante Eingaben geändert haben. So wird in einem Monorepository nicht „alles“ neu ausgeführt, sondern ausschließlich diejenigen Tasks, die durch die Änderungen wirklich berührt werden. Wenn die gleiche Task mit identischem Input erneut ausgeführt wird, werden die Ergebnisse direkt aus dem Cache abgerufen, statt neu berechnet. Darüber hinaus kann eine Bibliothek sogar Änderungen enthalten und trotzdem die Ergebnisse aus dem Cache nutzen, solange diese Änderungen für die Task nicht relevant sind. Die Inputs einer Task können konfiguriert werden. Beispielsweise ist durch Nx vorkonfiguriert, dass Tests nicht zum Input der Build-Task gehören. Änderungen an Tests invalidieren nicht den Cache des Build-Tasks. Diese Features sind besonders hilfreich, weil sie große Zeit- und Kosteneinsparungen bringen können.

Erweiterbar durch Plugins

Nx ist durch seine Plugin-Architektur erweiterbar. In klassischen Projekten enthält die package.json etwa Skripte für serve, build, test und lint. Diese Skripte können in Nx durch Plugins ersetzt werden.

Etwa bietet das Vite-Plugin Tasks für build und serve. Außerdem stellt es den Befehl watch-deps bereit, der automatisch alle abhängigen Pakete im Watch-Modus baut. Alle abhängigen Pakete, egal wie tief verschachtelt, werden automatisch bei Änderungen neu gebaut. So fallen inkompatible Änderungen sofort auf, weil alle relevanten Builds automatisch mitlaufen.

Neben diesen Plugins gibt es auch Plugins für JavaScript, Angular, Vue, React, Vitest und Java.

Fazit

Nx beschleunigt und vereinfacht die Arbeit in großen Monorepositories, indem es intelligente Task-Ausführung und deterministisches Caching nahtlos kombiniert. Das Ergebnis ist effizientes, reproduzierbares Task-Running über den gesamten Workspace: Tasks laufen nur dort, wo Änderungen wirklich relevant sind, in der korrekten Abhängigkeitsreihenfolge und oft direkt aus dem Cache. Das Plugin-Ökosystem (z. B. für Vite, ESLint oder Vitest) standardisiert gängige Workflows wie build, test, serve und watch und macht sie in jedem Paket einheitlich nutzbar. Gleichzeitig sorgen Visualisierung und Regeln wie enforce-module-boundaries für klare Architekturgrenzen und bessere Wartbarkeit. Kurz: Nx bringt Struktur, Geschwindigkeit und Sicherheit in den gesamten Entwicklungszyklus – besonders dort, wo viele Teams und Bibliotheken in einem TypeScript-Monorepo zusammenkommen.

Nächster Artikel

OWASP Top 10 (2025): Was sich ändert und warum schnelle Reaktion zählt

OWASP Top 10 (2025 RC):