I think there is more talk about the how of monorepos than the why or the what.
Once you know that you’re going to go (or convert to) the monorepo format, there are all sorts of interesting technical challenges like sharing packages (or not), shared config, and whatnot. But why do it at all? That it isn’t painfully obvious. Like, what even is a monorepo, and under what circumstances would I need one?
My first and only experience with monorepos is at CodePen where we’re now fully using a monorepo. It became most obvious to me in this situation:
- Next.js Site
— Ruby on Rails Site
— Shared Design System
— Shared Utilities
Code language: CSS (css)
Those are the top-level folders of very important actively developed things. In other words, rather than each of them being a literal repo, we nested them all together in a single repo with a single parent, like:
— cp (Monorepo)
— cpadmin (Next.js Site)
— cprails (Ruby on Rails Site)
— cplibrary (Bunch of React Components)
— cputil (Bunch of JavaScript/JSON files)
Code language: JavaScript (javascript)
So all these important things are essentially side-by-side. I don’t want to nest my Next.js site within my Ruby on Rails site. I maybe could, but it feels weird and is off-the-beaten-path for the involved frameworks. Even weirder to put a Ruby on Rails site underneath a Next.js root site. That type of file system nesting just feels unnatural and can cause actual problems like file watchers and build systems getting confused about what it’s seeing.
It’s even more clear when you look at things the “Sites” share. If you have a design system, it feels best to have it live at the same level as the multiple sites that are reaching for it. It would be extra weird (and likely present real challenges to things like deployment) for one site to reach up not only outside its own root, but then back down again into some other site to pluck out components.
In actuality, our own repo is more like this:
— cp (Monorepo)
— cpadmin (Next.js Site)
— cpxxx (More Future Next.js Sites)
— cprails (Ruby on Rails Site)
— cplibrary (Design System Components)
— cputil (Bunch of JavaScript/JSON utility files)
— cpclient (Shared Components/Hooks)
— cpprocessors (Bunch of AWS Lambdas)
— cpworkers (Bunch of Cloudflare Workers)
— cpgo (API and other servers)
— cpicons (Shared icons)
— cpstyles (Shared CSS)
— cpshots (Screenshot engine)
— cpsearch (Search engine)
Code language: JavaScript (javascript)
There is more. There is a lot of stuff that powers CodePen. Those integration tests gotta go somewhere to, ya know, test… the… integrations. It would be a pain in the ass if all this stuff was in separate repos. I would know, I was there. Now you pull, you got it all. It’s just easier.
What’s complicated is… a lot of stuff. Now for deployment, I can’t just “deploy everything in the repo”, which is a pretty common setup for tools like that. There needs to be code that detects when files in certain folders have changed and only deploy the changes in that folder in special particular ways. That’s non-trivial. Another complication is that not all site-building frameworks are designed to pluck files from outside their own root. I could go on and on, as the challenges of a monorepo are many.
But instead of getting more complex, let’s get less complex.
A monorepo could just be two things.
For example:
— Monorepo
— Docs Site
— Main Site
Two sites, but you just can’t be troubled to deal with them separately. Or it’s easier to have them both open and in sync all the time because you work on them together mostly.
Or maybe like:
— Monorepo
— Main Site
— Design System
Design systems are great, and it can make a lot of sense to keep them independent. Or even if the design system is baked into the main site, it still could be like:
— Monorepo
— Main Site
— Storybook
Your Storybook doesn’t need to be inside the main root because it doesn’t need to be deployed and changes to it probably shouldn’t trigger a deploy.
Or maybe it’s just one little thing that goes somewhere else like:
— Monorepo
— WordPress Site
— Cloudflare Worker
Those two things are going to be deployed very differently, and thus should probably be sibling folders rather than nested in one another.
Leave a Reply