Monorepo: alle code van een organisatie in één repository
Een monorepo (van "mono" = één, en "repository" = opslagplaats voor broncode) is één enkele digitale opslagplaats waarin een bedrijf of open-sourceproject de broncode van meerdere, soms tientallen of duizenden, afzonderlijke software-projecten samen bewaart. In plaats van dat elk onderdeel — een website, een app, een interne tool, een gedeelde bibliotheek — zijn eigen afgesloten "map" op een server krijgt, staat alles bij elkaar in één grote, doorzoekbare geheel.
Een handige vergelijking is een archiefgebouw. Bij de aanpak zonder monorepo ("polyrepo" genoemd) heeft elke afdeling van een bedrijf haar eigen apart pand met eigen toegangscontrole en eigen administratie. Bij een monorepo zitten alle afdelingen onder één dak, in hetzelfde gebouw met dezelfde regels, dezelfde beveiliging en dezelfde catalogus — makkelijker om dwars door afdelingen heen dingen terug te vinden en te veranderen, maar het gebouw moet dan wel groot en goed georganiseerd genoeg zijn om iedereen te herbergen.
Wat is het precies?
Om te snappen wat een monorepo is, helpt het eerst te weten wat een "repository" is. Softwareontwikkelaars gebruiken versiebeheersystemen — het populairste heet git — om elke wijziging aan code bij te houden, zodat je altijd kunt teruggaan naar een eerdere versie en kunt zien wie wat wanneer heeft aangepast. Zo'n verzameling code met zijn hele geschiedenis heet een repository, vaak afgekort tot "repo".
Traditioneel krijgt elk project zijn eigen repository: een "polyrepo"-aanpak, met soms honderden losse repo's naast elkaar. Een monorepo draait dat om: alle projecten, of in elk geval een groot deel ervan, leven in dezelfde repository, met dezelfde geschiedenis en dezelfde mappenstructuur.
Dat klinkt eenvoudig, maar het brengt technische uitdagingen met zich mee. Als honderden projecten in één repo zitten, wil je niet bij elke wijziging alles opnieuw bouwen en testen — dat zou veel te traag zijn. Daarom gebruiken monorepo's gespecialiseerde build tools (programma's die broncode omzetten in werkende software) zoals Bazel, Nx, Turborepo of Lerna. Deze tools houden een zogeheten dependency graph bij: een soort plattegrond die aangeeft welke onderdelen van welke andere onderdelen afhankelijk zijn. Wijzig je één bibliotheek, dan weet het systeem precies welke andere projecten daardoor geraakt worden en bouwt en test het alleen dié — een aanpak die "incrementeel bouwen" heet, omdat alleen het gewijzigde deel opnieuw wordt verwerkt in plaats van het geheel.
Wat wil men ermee bereiken?
De belangrijkste belofte van een monorepo is consistentie. Omdat alle code op één plek staat en gebruikmaakt van dezelfde versies van gedeelde bibliotheken, ontstaat er minder snel een situatie waarin verschillende teams stiekem verschillende, onderling onverenigbare versies van hetzelfde stuk code gebruiken — een probleem dat in de polyrepo-wereld bekendstaat als "dependency hell".
Een tweede doel is het vergemakkelijken van grootschalige herstructureringen ("refactoren"). Wil je een functienaam wijzigen die door twintig verschillende projecten wordt gebruikt, dan kan dat in een monorepo in principe in één keer, in één zogeheten "atomic commit" — een enkele, samenhangende wijziging die tegelijkertijd meerdere projecten aanpast en die als één geheel wordt geaccepteerd of afgewezen. In een polyrepo-opzet moet je twintig aparte repositories langs, elk met een eigen goedkeuringsproces, wat traag en foutgevoelig is.
Daarnaast bevordert een monorepo het hergebruiken van code: een team dat een handige interne bibliotheek heeft geschreven, hoeft die niet apart te publiceren en te documenteren voor andere teams — iedereen kan er meteen bij. Ten slotte noemen voorstanders ook betere zichtbaarheid en samenwerking: iedereen kan in principe alle code inzien en doorzoeken, wat losstaande, verborgen "eilandjes" van kennis tegengaat.
Voorbeelden uit de praktijk
Het bekendste voorbeeld is Google. In een veelgeciteerd artikel uit 2016 in het tijdschrift Communications of the ACM, getiteld "Why Google Stores Billions of Lines of Code in a Single Repository" van Rachel Potvin en Josh Levenberg, beschreef het bedrijf hoe vrijwel al zijn broncode in één enorme interne repository staat, beheerd met een intern systeem genaamd Piper. Het bijbehorende bouwsysteem heette intern Blaze; in 2015 bracht Google daarvan een open-source variant uit onder de naam Bazel, die inmiddels ook buiten Google veel gebruikt wordt.
Ook Microsoft is een veelgenoemd voorbeeld. Rond 2017 verhuisde het bedrijf de broncode van Windows — naar schatting destijds enkele miljoenen bestanden en enkele honderden gigabytes groot — naar het gewone versiebeheersysteem git. Omdat git van zichzelf niet goed met zulke enorme repositories overweg kon, ontwikkelde Microsoft daarvoor een uitbreiding genaamd GVFS (Git Virtual File System), die later is doorontwikkeld tot de tools VFS for Git en Scalar.
Meta (het moederbedrijf van Facebook en Instagram) beheert eveneens grote interne monorepo's, onder meer voor de website-codebase, en gebruikte daarvoor lange tijd het zelfontwikkelde bouwsysteem Buck, dat inmiddels is opgevolgd door Buck2.
In de open-sourcewereld van JavaScript ontstond rond 2015-2016 bij het Babel-project (een veelgebruikte tool om moderne JavaScript-code compatibel te maken met oudere browsers) de tool Lerna, gemaakt om meerdere samenhangende npm-packages (herbruikbare stukjes JavaScript-code) in één repository te beheren en gezamenlijk te publiceren. Latere, populaire opvolgers zijn Nx, ontwikkeld door het bedrijf Nrwl, en Turborepo, gebouwd door Vercel nadat dat bedrijf de oorspronkelijke makers in 2021 overnam.
Hoe ver is de techniek?
Monorepo-tooling is inmiddels volwassen en wordt op grote schaal gebruikt, zowel binnen grote technologiebedrijven als in open-sourceprojecten van uiteenlopende omvang. Voor kleinere teams met een handvol samenhangende projecten is de overstap naar een monorepo met tools als Nx of Turborepo tegenwoordig relatief eenvoudig.
Bij zeer grote schaal blijven er echter praktische obstakels. Git is van oorsprong niet ontworpen voor repositories met miljoenen bestanden en jarenlange geschiedenis; standaardbewerkingen zoals het ophalen ("clonen") van de repository of het doorzoeken ervan kunnen dan traag worden. Bedrijven als Google en Microsoft hebben daarom eigen, aangepaste versiebeheeroplossingen moeten bouwen in plaats van kant-en-klare git te gebruiken.
Een tweede obstakel is continuous integration en continuous deployment (CI/CD): het automatisch testen en uitrollen van elke codewijziging. In een monorepo kan één kleine wijziging in theorie gevolgen hebben voor tientallen andere projecten, wat de teststrategie complexer maakt dan bij een geïsoleerde polyrepo. Ook het beheren van toegangsrechten — wie mag welk deel van de code zien of wijzigen — is lastiger te regelen dan wanneer elk project zijn eigen, apart afgeschermde repository heeft. Er is geen brede consensus dat een monorepo altijd beter is dan een polyrepo; de keuze hangt sterk af van teamgrootte, organisatiestructuur en het soort software.
Wie werken eraan?
De belangrijkste ontwikkelaars van monorepo-tooling zijn tegelijk de grootste gebruikers ervan. Google onderhoudt en ontwikkelt Bazel verder. Meta doet hetzelfde met Buck2. Microsoft blijft investeren in het schaalbaar maken van git zelf, onder meer via het Scalar-project en bijdragen aan de open-source git-gemeenschap. In de commerciële open-sourcehoek zijn Nrwl (met Nx) en Vercel (met Turborepo) actief, terwijl de bredere JavaScript-gemeenschap ook zelf tools als pnpm workspaces en Lerna onderhoudt.
Verder lezen
- Bazel — officiële site van Google's open-source bouwsysteem voor monorepo's.
- monorepo.tools — overzichtssite met uitleg en vergelijking van verschillende monorepo-tools.
- Nx — documentatie van het populaire monorepo-gereedschap van Nrwl.
- Turborepo — officiële site van Vercels build-systeem voor monorepo's.
- Git — officiële documentatie van het versiebeheersysteem waarop de meeste monorepo's zijn gebouwd.