DEV Community

Andrei Xavier de Oliveira Calazans
Andrei Xavier de Oliveira Calazans

Posted on

Can we implement a Monorepo structure without Yarn Workspaces or Lerna?

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)

Collapse
 
mauriciord profile image
Mauricio Reatto Duarte • Edited

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...

Collapse
 
controlplusb profile image
Sean Matheson • Edited

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?

Collapse
 
andreicalazans profile image
Andrei Xavier de Oliveira Calazans

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.