In order to simplify dependency management, code reuse, and collaboration across teams, many projects have sought out to use the Monorepo structure.
To implement this structure most projects decide either on Yarn Workspaces
or Lerna
to accomplish this feat. The difference between the two can be simplified to the fact Lerna
can do everything Yarn Workspaces
can including use it as a base, and provide sophisticated publishing and version management features to even publish projects independently from each other.
The Problem
Yarn Workspaces
has proven to be quite burdensome to maintain when working with React Native due to React Native's assumptions. Overall, as your codebase progress and new updates occur, you might need to update and fix the Monorepo structure. To avoid having this kind of issue, and to also enjoy similar benefits. You could instead structure your Monorepo without Workspaces
.
How could we structure a Monorepo without Yarn Workspaces
?
Under the same repository, you could have multiple independent projects linked by installing it via a relative path. Each project or module will have its own package.json
file which you can create with yarn init
.
- apps
- app_one
- app_two
- shared
- module_one
- module_two
app_one
and app_two
can consume the shared module by installing it as follow:
yarn add file:../../shared/module_one
This will add the following to your package.json
"module_one": "file:../../shared/module_one",
Note, To avoid reinstalling the same dependencies make sure to declare modules as peerDependencies
inside your shared modules if you also use them.
This approach has the benefit of being compatible with NPM as well.
Possible Problems
If your shared modules have external dependencies and for some reason, you install them by running yarn inside shared/*
, you have to always remember to remove the node_modules
folder before running your app, else you will have name collisions.
Conclusion
There is a price to be paid by abstractions. This does not mean abstractions are negative, it only means we should look for simplicity to achieve our goals, else we will die maintaining. I hope this post displayed a simple and less abstracted way to handle Monorepo
structures.
Top comments (3)
Some time ago, I read in a Typescript book that it has some structure that the idea of monorepo would be possible.
I don't remember now, but I think it was something like TS Projects.
typescriptlang.org/docs/handbook/p...
I've been leaning into this idea recently. How has this approached worked for you over the last few years? Do you have any example repository or additional points you believe worth sharing?
Hey Sean, I don't have a public repo to share. I did this on a small shortlasting project which I am no longer part of.
The one drawback to this kind of solution is that there is large tendency to start abstracting some of the logic away with scripts and if you catch your team doing so it will be better to rely on a Monorepo solution.
Recently there was an increased offering and popularization of Monorepo tools like Nx and TurboRepo that do way more than just organize the Monorepo struture for you. Might be worth looking into that as well.