We're gonna talk about developing at scale with NxMonoRepos. So what is a MonoRepo? MonoRepo is a single repository that contains multiple distinct projects with well-defined relationships. So, you know, multiple different apps working together, or you could it could be one app but with multiple like sub projects inside of it. And then you need to have well-defined relationships between them. You can't just if you just dump all the code of two different apps in the same repo. We call this code co-location and it's a mess. And you you'll run into lots of problems with that. And let's talk about what those things are.
So a monorepo is great for lets you have atomic changes, lets you share code easily, and lets you have a single set of dependencies. So let me go into each of these and explain what they are. So atomic changes are, let's say you have an application that consumes a UI library. And if you have that UI library in a separate repo from your application, then the change workflow goes something like this. Say you make a change to the UI library that breaks a test in the application. So you have to publish that UI library, and then at some point later, the application developer bumps up their version of the library and realizes, hey, you broke my application. So then they tell you about it, or they file an issue about it. And then the library developer has to come back and say, okay, I'm gonna fix that bug and then publish a new version of it that will fix the bug. And then later, a few days later, the application developer bumps their version again and says, okay, that fixed it. So that whole life cycle, that's a minimum of a week probably, of actual real developer time. Before the change is made to it's actually fixed and corrected. Whereas if they were the same repo, then the library developer would just run the tests before they even make the commit. They would just run the test and say, wait, I broke that app, I'm gonna fix it. So it goes from a week cycle time to like 30 minutes cycle time and you're not doing that contact switching, going back to this thing you worked on a week ago to finally fix it. That's one benefit of a Monorepo. Second benefit is sharing code. So if you have some user logic to validate whether a username is valid, and you want to reuse that logic across multiple applications or multiple subsections of your app. If you were gonna do that in separate repos, you'd have to publish that and keep the version numbers in sync. Whereas in a monorepo, all you need to do to share that logic is to export a function and then just reuse that function wherever it's needed. So it makes it dead simple to keep that logic in sync. If you wanted to change this logic somehow, you just update that function and everywhere instantly uses the new updated logic. The other benefit is having a single set of dependencies. So, say if you have multiple different versions of your framework of Angular or react, that can cause weird, strange bugs. If you have a library that's on an old version of react and the applications on a newer version of react, there can be like, hard to debug. Hard to debug runtime errors that can be caused by that. The other issue is that whenever you have multiple applications on different, well, you have multiple applications, usually there's one application, that's the main thing that gets worked on all the time. So that's going to be at the latest version of React. Version of the framework, but then if you're going to have another application that's you know you updated every three months or so maybe whenever you get around to it, and then whenever you go to update that, it's always a pain. Because you have to remember, okay, what were the tricky things about upgrading to that version of React that was six months ago, or a year ago. And you have to go through all the same pain points that you did the first time, but 12 months later. Whereas it's a lot easier to do all the application upgrading at the same time. Because you're solving the same problem in 10 different places, instead of solving the same problem in one place, so it's not that hard. Whereas if you do it 10 different times over the course of a year, that's really painful.
Code collocation is where you just drop code together without having a monorepo tooling in place. So one of the issues so you can have running unnecessary tests, not having code boundaries and having inconsistent tooling. So unnecessary tests, let's say you change the products homepage project, and that depends on a UI library. So if you make changes to the products homepage, there's no way you broke the test for the product UI library. So there's no point running those tests, but without your tooling knowing about how this dependency graph, how that dependency actually works. There's no way for your tooling to say, these tests you need to run, these tests you don't need to run. So you need to have something that knows this dependency graph. And so you could theoretically do that yourself. You say I know that this test needs to run, these other tests don't. But a normal repo that has multiple applications, the product graph looks more like this. Or even, I've seen graphs that have thousands of nodes in it like this. And so there's no way you can do that in your head to make sure you get all the tests done correctly every time. So you want to have a tool that can do this for you. So you make sure you run all the tests you need to run, but not any of the tests that are guaranteed not to have broken. The other thing is code boundaries. Let's say you have your code in a shared repo, and you have some function that you're playing around with. It's intended for internal use within your project, and you don't want other people to use it, because it might change frequently, right? But somebody reaches in and starts using that function in their application. And then at some point later, you change it. You've broken their app, and they're upset at you. And so, now you're forever on the hook for keeping that function with the same API, or fixing their code wherever it's using it. So there needs to be some way of saying, these functions are available for you to use. These functions are not available for you to use. So that you can clearly say, here's the boundary, and this is my stuff, internal stuff. This is public stuff. And the other thing is inconsistent tooling. So every application, every project has, you put in NPM script, you have all sorts of weird flags and scripts. And so, whenever you're going into new code base, you have to figure out, what does this mean? And why would I ever run this? And it's really hard to know that in each new application. So you need to have some way of making those things discoverable and well-documented. So this is what Nx can help with.
Comments