Engineering

Monorepo-changelogs: één, of één per package?

5 min lezen

Een monorepo huisvest meerdere apart uit te brengen dingen in één repository, en een changelog moet eerst een vraag beantwoorden: interesseert het de lezer om de repo, of om één specifiek package erin? De meeste teams beslissen dit nooit bewust. Ze beginnen met één changelog omdat er één repo is, voegen gaandeweg packages toe, en eindigen met een log waarin iemand die de CLI gebruikt langs veertig irrelevante backend-regels moet scrollen om die te vinden die zijn fix uitbracht. Wat de juiste vorm bepaalt, is niet de structuur van de repository, maar wie het log leest en wat die persoon al weet te zoeken.

Wat maakt de changelog van een monorepo anders dan die van een enkele repo?

Een changelog voor één repo heeft een impliciet publiek: iedereen die het enige gebruikt wat die repo bouwt. Het publiek van een monorepo splitst per package, en packages in dezelfde repo worden vaak op verschillende schema’s uitgebracht, aan verschillende afnemers, op verschillende stabiliteitsniveaus. Een bibliotheek gepubliceerd in een register en een intern beheertool kunnen in dezelfde monorepo leven en voor de lezer van de changelog bijna niets gemeen hebben.

Repo-vormTypische lezerPassende changelog
Eén uit te brengen appIedereen die het product gebruiktEén log, voor de hele repo
Bibliotheek-workspace (meerdere gepubliceerde packages)Wie van een specifiek package afhangtEén log per package
App plus interne toolsTwee verschillende publieken zonder overlapGesplitst per publiek, niet per map
App plus eigen SDKProductgebruikers, en SDK-integratorsTwee logs: productgericht en SDK-gericht

Heeft elk package zijn eigen changelog nodig?

Alleen die met een onafhankelijk publiek. Een package gepubliceerd in een register heeft zijn eigen log nodig, omdat wie het installeert geen reden heeft om iets anders in de repo te lezen, en releasetools voor monorepo’s zoals Lerna en Changesets schrijven een CHANGELOG.md per package, naast de package.json. Een interne utility met één afnemer, de app die al in dezelfde repo leeft, heeft geen apart log nodig; de wijzigingen ervan opnemen in de regels van die app is nuttiger dan een tweede bestand dat niemand buiten het team opent.

De test is dezelfde die bepaalt of een willekeurige regel in een changelog thuishoort: zou de lezer het opmerken of erom geven, en kan die er iets mee doen. Pas dit toe per package, niet per map, en een repo met twaalf packages kan eindigen met twee echte changelogs en tien packages die er simpelweg geen nodig hebben.

Hoe weet je welk package welke changelog-regel veroorzaakte?

Label elke regel met zijn package op het moment dat de regel geschreven wordt, niet achteraf door te inspecteren welke bestanden een commit raakte. Een commit die een gedeelde interne bibliotheek fixt kan een changelog-regel opleveren in elk package dat ervan afhangt, en bestandspaden alleen kunnen niet zeggen welke van die stroomafwaartse regels de lezer echt moet zien; alleen een persoon die beslist “dit is zichtbaar voor gebruikers van package A en niet voor gebruikers van package B” kan dat. Conventional commits helpen hier mechanisch, door het package in elke commit te noemen, maar de scope levert nog steeds alleen een concept op. Dezelfde tweelaagse regel uit dat artikel geldt per package: een concept met de juiste scope heeft alsnog een menselijke pas nodig voordat het is verwoord voor de echte lezer van dat package.

Wat heeft een gedeelde changelog nodig dat een changelog voor één repo niet heeft?

Een package-label op elke regel, vooraan, voor de beschrijving, zodat een lezer die het log doorneemt in één keer alles kan overslaan dat niet van hem is. Zonder dat label leest een gedeeld log als een willekeurige feed, en een lezer die zich voor één package interesseert heeft geen manier om te filteren behalve onthouden welke regels tellen, wat niemand na de eerste week meer doet.

## 2026-09-07

### [cli] Toegevoegd
- `acme push --dry-run` laat zien wat verzonden zou worden
  zonder het echt te verzenden.

### [core] Opgelost
- De retry-backoff reset niet meer bij een succesvol verzoek dat
  een leeg body teruggeeft.

Twee regels, twee publieken, één blik om ze te onderscheiden. Een workflow in Changesets-stijl bouwt deze labeling rechtstreeks in het releaseproces: een bijdrager schrijft een korte, package-specifieke notitie naast zijn wijziging, en de tool stelt de changelogs per package en de versiesprongen samen uit die notities op het moment van de release, in plaats van te proberen packagegrenzen achteraf te reconstrueren uit een samengevoegde commitgeschiedenis.

Hoe verhoudt versionering zich tot een monorepo-changelog?

Onafhankelijk geversioneerde packages hebben hun eigen changelog nodig omdat ze hun eigen versienummer hebben, en een gedeelde changelog kan niet uitdrukken “package A ging van 2.1 naar 2.2 terwijl package B op 1.4 bleef” zonder twee logs in één bestand te worden. Semantic versioning en je changelog behandelt hoe een versienummer zou moeten mappen op changelog-categorieën; in een monorepo moet die mapping per package worden toegepast, omdat een breaking change in het ene package geen breaking change is voor een zusterpackage dat er niet van afhangt.

Een repo die één product uitbrengt als één uit te brengen eenheid, ook al is die opgebouwd uit veel interne packages, heeft dit probleem niet: de packages delen een versie omdat ze altijd samen worden uitgebracht, en één changelog is correct.

Hoe passen git-tags in een monorepo?

Dezelfde regel uit git-tags, releases en je changelog geldt, per package toegepast: een package met een eigen versie heeft een eigen tag-prefix nodig, typisch packagenaam@1.4.0 in plaats van een kale v1.4.0 die niet kan zeggen bij welk package het hoort. Een monorepo die alleen met kale versienummers is getagd, kan later niet beantwoorden “wat zat er in core toen cli 2.2 uitbracht”, omdat niets op schijf vastlegt bij welk package die tag daadwerkelijk hoorde.

FAQ

Heb ik een aparte changelog nodig voor elk package in een monorepo? Alleen voor packages met een onafhankelijk publiek, meestal alles wat in een register wordt gepubliceerd. Een package met één interne afnemer die al in dezelfde repo leeft, kan opgaan in het log van die afnemer in plaats van een eigen log bij te houden.

Wat labelt een changelog-regel met het juiste package? De persoon die de regel schrijft, op het moment dat hij die schrijft, niet een automatische scan van gewijzigde bestandspaden. Een wijziging in een gedeelde bibliotheek kan een andere regel opleveren in elk package dat ervan afhangt, en alleen een mens kan beslissen wat elk van die stroomafwaartse regels eigenlijk moet zeggen.

Zou een monorepo één versienummer voor alles moeten gebruiken? Alleen als elk package altijd samen met de rest wordt uitgebracht. Als packages ooit onafhankelijk worden gepubliceerd, hebben ze onafhankelijke versies nodig, en onafhankelijke versies hebben onafhankelijke changelogs nodig om ergens op te slaan.

Vervangt een monorepo-changelogtool de menselijke redactiestap? Nee. Tools zoals Changesets automatiseren het verzamelen en samenstellen van notities per package op het moment van de release; de notitie zelf, geschreven in de taal van de lezer in plaats van die van de bijdrager, blijft net als bij elke andere changelog-pipeline het werk van een persoon.


De technische beweringen in dit artikel zijn niet onafhankelijk gecontroleerd. Klopt er iets niet, laat het ons weten, dan corrigeren we het.

Meer op changeloop: Changelog-generator, Documentatie voor ontwikkelaars

changeloop
Het team achter een changelog die de cirkel rondmaakt. Je gebruikers vragen iets, je team levert het, degene die het vroeg hoort ervan.