© vectorpouch/Shutterstock.com
Monorepos: Ein Konzept zur Verwaltung komplexer Codebasen

Ab ins Repository!


Monorepos ist keine neue Erfindung. Die Ansätze werden von großen Unternehmen wie Facebook und Google zur Verwaltung komplexer Codebasen genutzt. Doch was steckt hinter dem Begriff Monorepos? Welche Vor- und Nachteile bringt dieses Konzept mit, was gibt es bei der Umsetzung zu beachten und welche Werkzeuge können Sie bei der Entwicklung unterstützen?

Die Idee von Monorepos ist nicht neu. Große Unternehmen wie Facebook, Google oder Twitter nutzen diesen Ansatz, um große Codebasen zu verwalten. Aber auch im kleineren Umfang setzen sich Monorepos zunehmend durch. Gerade Bei Open-Source-Projekten erfreuen sich Monorepos zunehmender Beliebtheit. Ein populäres Beispiel einer Applikation, die auf ein Monorepo setzt, ist Yarn, der JavaScript-Package-Manager von Facebook. Um diesem Trend zu folgen, müssen Sie jedoch schon ein bisschen mehr tun als nur Ihren Quellcode in ein riesiges Repository zu stecken. Was genau die Gründe sind, die für ein Monorepo sprechen, was Sie dabei beachten müssen und welche Werkzeuge Sie bei der Entwicklung unterstützen, sehen wir uns im Zuge dieses Artikels an. Anhand einer kleinen Beispielapplikation in JavaScript sehen Sie, wie sich die Konzepte und Lösungsansätze in der Praxis umsetzen lassen. Doch zunächst zur Frage: Was ist denn ein Monorepo?

Was steckt hinter dem Begriff?

Im Begriff Monorepo steckt eigentlich schon alles, was Sie wissen müssen. Beim Konzept von Monorepos wird die gesamte Codebasis in einem Repository verwaltet. Am besten lässt sich dieser Ansatz anhand eines praktischen Beispiels zeigen. Ein Projekt, das auf einem Monorepo aufbaut, ist Jest, das JavaScript-Testframework von Facebook. Werfen Sie einen Blick in das GitHub-Repo des Projekts, fällt auf den ersten Blick das Verzeichnis packages auf. Die übrige Projektstruktur gleicht überwiegend einem Standardprojekt. Im packages-Verzeichnis finden Sie eine ganze Reihe weiterer Verzeichnisse. Diese Pakete stellen die einzelnen Bestandteile vom Core-Paket über das CLI bis hin zum Mock-Paket des Projekts dar.

Natürlich ist es sinnvoll, in einem Monorepo zusammengehörige Pakete zu gruppieren, es ist jedoch nicht verpflichtend. So haben Sie auch die Möglichkeit, thematisch vollständig getrennte Projekte in einem Monorepo zu verwalten. Dieser Ansatz wird jedoch in den meisten Fällen für interne Projekte verfolgt. Bei öffentlichen Projekten wird darauf geachtet, das Monorepo so zu dimensionieren, dass es die gesamte Codebasis des Projekts umfasst.

Ein Monorepo ist leicht als solches zu erkennen, wenn es über eine Paketstruktur wie Jest verfügt und diese Pakete als weitestgehend eigenständige Subprojekte verwaltet werden. Im Fall von Jest weist jedes Paket eine eigene package.json- und readme-Datei auf. Auch die Unit-Tests liegen hier in den jeweiligen Paketen.

Monorepos bedeuten keine Abkehr von modularen Architekturen oder Microservices. Im Gegenteil, sie unterstützen solche Architekturansätze und lösen einige Probleme, die mit einer solchen Architektur einhergehen. Da sich Monorepos auf der Ebene der Source-Code-Verwaltung bewegen, haben sie nur beschränkten Einfluss auf die Architektur einer Applikation. Die Auswirkungen auf den Build-Prozess und das Deployment einer Applikation sind dagegen stark. In diesem Bereich sind in den letzten Jahren zahlreiche Werkzeuge entstanden, die die Komplexität reduzieren, die durch die Verwendung von Monorepos eingeführt wurde. Prominente Vertreter dieser Werkzeuge sind das Verwaltungswerkzeug Lerna und die Build-Tools Bazel und Buck. Wenn sich große Unternehmen und Open-Source-Projekte für diesen Ansatz entscheiden, scheint es gute Gründe dafür zu geben. Einen solchen Paradigmenwechsel vollführt man schließlich nicht nur aus einer Laune heraus.

Was spricht für ein Monorepo?

Den gesamten Quellcode mehrerer Pakete oder Projekte in einem Repository zu verwalten, klingt verdächtig nach einem monolithischen Ansatz. Wie also passt ein solches Konzept in eine Welt der verteilten Softwareentwicklung? Die Antwort liegt auch hier auf der Hand: Gehen Sie von einer modular aufgebauten Frontend-Applikation aus. In diesem Fall gibt es ein zentrales Paket, das den Einstieg in die Applikation darstellt. Dieses Paket stellt die übergeordnete Infrastruktur zur Verfügung, in die die weiteren Pakete der Applikation integriert werden. Diese weiteren Pakete kümmern sich dann nur noch um bestimmte Aspekte der Applikation. Ist eine Kommunikation zwischen verschiedenen Teilen der Applikation erforderlich, wird sie über einen zentralen Nachrichtenkanal mit standardisierten Schnittstellen ermöglicht. Damit ist eine größtmögliche Entkopplung der einzelnen Pakete sichergestellt. Ein entscheidender Nachteil ist hier, dass die Oberfläche der Pakete dennoch wie aus einem Guss aussehen muss, damit sich für den Benutzer ein einheitliches Erscheinungsbild ergibt. Aus diesem Grund wird hier häufig auf Komponentenbibliotheken zurückgegriffen. Diese stellen visuelle Komponenten zur Verfügung, die applikationsweit verwendet werden. Sie sorgen dafür, dass ein Button in jedem Paket gleich aussieht. Dieses Konzept startet bei atomaren Elementen wie Buttons und reicht bis hin zu komplexeren Elementen wie DataTables oder Dialogen. Wird die Komponentenbibliothek als eigenständiges Paket verwaltet, können alle weiteren Pakete es einbinden und verwenden. Eines der Hauptargumente, das für ein Monorepo spricht, ist also ein vereinfachtes Code Sharing zwischen unabhängigen Paketen. Dieses Code Sharing endet jedoch nicht bei den Komponenten im Frontend. Auch gemeinsam genutzte Logik und Hilfsfunktionen lassen sich gut abstrahieren und in Paketen organisieren, die dann mehreren Paketen zur Verfügung stehen. Wichtig ist hierbei, dass sich keine applikations- beziehungsweise paketspezifische Logik in den gemeinsam genutzten Paketen befindet.

Mit den unabhängigen Paketen bleibt die Möglichkeit erhalten, dass mehrere Teams gleichzeitig am Quellcode arbeiten. Da jedem Entwickler stets der gesamte Quellcode des Repositorys zur Verfügung steht, besteht die Möglichkeit, sich Inspirationen für Lösungen aus den anderen Paketen zu holen und so auch ähnliche Ansätze zu verfolgen. Die gemeinsame Codebasis sorgt auch dafür, dass Fehler, die in einem zentralen Paket behoben wurden, allen Teams sofort zur Verfügung stehen und nicht erst mühsam integriert werden müssen.

Werden Hilfs- oder Komponentenbibliotheken in eigene Pakete ausgelagert, ist durch den Monorepo-Ansatz sichergestellt, dass alle Pakete den gleichen Stand haben, es gibt eine Single Source of Tru...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang