Though, as you say and I commented below they’re not mutually exclusive. A wrapper or even an entirely separate service can exist alongside others.
One dark side of this is being able to “reach inside” other parts of the monorepo and blur application boundaries.
Monorepos are also a great technique for tackling large legacy codebases. When the rot is all in one designated place, it becomes easier to encourage good developer habits on new code created in new, separated repo(s).
Speaking from experience I've worked on a team operating through a monorepo project that came out real well. The codebase was mostly golang, so everything lived in the GO_PATH, but for the most part the typescript in the UI side of the repo didn't complain. Testing and code quality was a higher priority, as well, which may have contributed to its success.
I have also worked on a monorepo project that had minimal tests and automation, that soon grew monstrous and ultimately needed refactoring. That was a big pile of coffeescript, es6 and java that ultimately refactored into three different node modules and two microservices.
Javascript and its module packaging tends to conform better to polyrepo patterns. golang code all wants to be in the same place, and java repos have their own desired nested directory structures. These two languages tend to encourage monorepo design patterns.
Monorepo or Polyrepo, the correct answer is whatever works for your team and task at hand.
I'm seeing these two things conflated in this thread.
In some cases, this could be two separate backend projects where you want to re-use the same deployment pipeline.
Often, I find that API wrappers are something that I share across frontends and backends in the JS world, so it often makes sense to separate my projects into:
- backend
- frontend
- common
In Typescript I really like this pattern and can namespace shared types so that it’s very clear to the future reader that this type is probably used outside of the current context.
So, to reply to your comment — I think the term “monorepo” can encompass a lot of different project types.
I think Dan Luu covers the bases quite well here:
Need to change a function signature or interface? Cool, global find & replace.
At some point monorepos outgrow their usefulness. The sheer amount of files in something that’s 10K+ LOC ( not that large, I know ) warrants breaking apart the codebase into packages.
Still, I almost err on the side of monorepos because of the convenience that editors like vscode offer: autocomplete, auto-updating imports, etc.