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-vorm | Typische lezer | Passende changelog |
|---|---|---|
| Eén uit te brengen app | Iedereen die het product gebruikt | Eén log, voor de hele repo |
| Bibliotheek-workspace (meerdere gepubliceerde packages) | Wie van een specifiek package afhangt | Eén log per package |
| App plus interne tools | Twee verschillende publieken zonder overlap | Gesplitst per publiek, niet per map |
| App plus eigen SDK | Productgebruikers, en SDK-integrators | Twee 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.