Working With Monorepos
Working with monorepos
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
Lesson Transcript
[00:00 - 00:08] We're going to be using a mono repo for our architecture. That means a single repository for everything in case you're not familiar with the term.
[00:09 - 00:21] And if that's the case, then it might strike you as a little bit lazy or messy perhaps. I think as engineers, we all have some slight OCD and we tend to like to put things into boxes.
[00:22 - 00:31] It's just sort of a natural instinct to us. We like to make things nice and orderly and setting up repositories from the start feels like a very nice way of starting a new project.
[00:32 - 00:55] And it's definitely a good skill or personality trait in a developer because I think we all know that being overly pedantic about details that might otherwise seem trivial is what makes a code base maintainable in the long run. You have to care about details that normal people, if you will, would simply go really, is this really necessary?
[00:56 - 01:05] Have two engineers, yes, that is absolutely necessary. But this also means that I think that this is a personality trait that we need to keep and check a little bit because it feels like a virtue.
[01:06 - 01:14] And so it's easy to let that just run and not control it. And it doesn't always add value to what we're doing.
[01:15 - 01:20] So I have this little, well, it's not a timeline. It's a journey.
[01:21 - 01:25] I call it the code journey. And this is just a general guideline.
[01:26 - 01:32] It's absolutely not a rule that must be followed. I break it all the time, but it's just an idea to get you started.
[01:33 - 01:39] So this is how I think about code when I'm writing something new. I will tend to start it in line.
[01:40 - 02:01] So if say I'm writing some new UI code, I will possibly just start it in line in the component that's going to be adding this UI. And only when I figure out that, okay, this is on the right track, when I'm starting to get a sense of what I'm doing, then maybe I will extract it into its own component.
[02:02 - 02:12] And as that component grows and becomes perhaps useful to other files as well, then I will move it into its own file. Now I often start with creating a file from the get-go.
[02:13 - 02:23] I even start further to the right in this line, but as a general guideline, it 's good to start like this, I think. I will then see where this file belongs.
[02:24 - 02:41] And the more I use it, the more generally applicable it becomes, and the more generic it becomes, the further up in the directory tree I'm going to move it. My directory tree tends to sort of mirror the levels of abstraction in the code .
[02:42 - 02:57] This doesn't match 100% and it's not always applicable, but that does sort of seem to be how things work, at least the way I end up structuring my code. The last folder that I will probably have is some sort of shared folder.
[02:58 - 03:12] At least I typically have that for components and hooks. It's a little bit different for other things, but maybe there's going to be a util folder for the server or something where I have really generic stuff that can be used all over the place.
[03:13 - 03:37] But if I find out that this is actually something that can be used by multiple packages or it really is very generic, then maybe I'll create an npm package, so to speak, in my monorepo. I'm going to be going over this when we reach the workspaces lesson, because we 're going to be using workspaces, which is sort of a way to create little npm packages in your repository.
[03:38 - 03:59] And then finally, if something is actually useful to others or I just feel like this is something I'm going to be using in more projects, then maybe I will end up creating an npm package, because then it's just so generic that it really should be published. It could be a private package, but I prefer to try to make things open source if that is possible.
[04:00 - 04:15] So from that perspective, I would argue that a monorepo is at least the obvious place to start. Even if you decide later on that it doesn't work for you for whatever reason, it is just the simpler solution to things, just having one place for everything.
[04:16 - 04:25] So why not start there and then split things up if you decide later on that it just doesn't work for you? There are some significant upsides to having everything in one place.
[04:26 - 04:32] For instance, it's much easier to share things like Linter settings and Type Script configurations. We're going to be looking at that in a following lesson.
[04:33 - 05:02] More importantly though, I would say that the fact that everything is synchronized, so for your services, they back in and front end or possibly other services if you have them, for them to be synchronized in say a branch makes it much easier to try out things that are requiring changes in both of those or more of those services. It's also easier for onboarding when you have a new team member, because there 's just one repo that they need to check out and they will have everything there.
[05:03 - 05:17] There are some downsides too as well. For instance, there's a higher risk of merge conflicts, which is obvious when you just have one repository, everybody's going to be working in that at the same time and there's a higher chance that there's going to be some conflict somewhere.
[05:18 - 05:33] But in my opinion, this is actually an expression of a conflict in the structure itself. And so if you didn't have it in the Monor repo, you would probably just be experiencing this in a more unpleasant way at runtime in one fashion or the other.
[05:34 - 05:44] There can be an issue with disk space if the repo grows very large. I know that both Google and Microsoft have solutions for this with actually doing something particular with Git.
[05:45 - 05:54] Not sure how that works, but this is something I have never experienced anywhere. So I think that's a very limited problem for most people.
[05:55 - 06:08] You may run into a situation where your lint two settings and TypeScript configurations and what else you have doesn't actually work for every project in the repo. And so maybe that shared thing loses its value.
[06:09 - 06:16] That's a potential, but that also seems like a very trivial thing to me. The last thing that could be breaking this is if you have some compliance rules .
[06:17 - 06:26] If one team is simply not allowed to work or see a piece of code, obviously that might create a tension for you. But we're going to assume here that there are no specific compliance rules.
[06:27 - 06:33] I don't think there would be for a booking system anyway. So we are going to use the mono repo and hopefully you will be able to as well.
We're going to be using a mono repo for our architecture. That means a single repository for everything in case you're not familiar with the term. And if that's the case, then it might strike you as a little bit lazy or messy perhaps. I think as engineers, we all have some slight OCD and we tend to like to put things into boxes. It's just sort of a natural instinct to us. We like to make things nice and orderly and setting up repositories from the start feels like a very nice way of starting a new project. And it's definitely a good skill or personality trait in a developer because I think we all know that being overly pedantic about details that might otherwise seem trivial is what makes a code base maintainable in the long run. You have to care about details that normal people, if you will, would simply go really, is this really necessary? Have two engineers, yes, that is absolutely necessary. But this also means that I think that this is a personality trait that we need to keep and check a little bit because it feels like a virtue. And so it's easy to let that just run and not control it. And it doesn't always add value to what we're doing. So I have this little, well, it's not a timeline. It's a journey. I call it the code journey. And this is just a general guideline. It's absolutely not a rule that must be followed. I break it all the time, but it's just an idea to get you started. So this is how I think about code when I'm writing something new. I will tend to start it in line. So if say I'm writing some new UI code, I will possibly just start it in line in the component that's going to be adding this UI. And only when I figure out that, okay, this is on the right track, when I'm starting to get a sense of what I'm doing, then maybe I will extract it into its own component. And as that component grows and becomes perhaps useful to other files as well, then I will move it into its own file. Now I often start with creating a file from the get-go. I even start further to the right in this line, but as a general guideline, it 's good to start like this, I think. I will then see where this file belongs. And the more I use it, the more generally applicable it becomes, and the more generic it becomes, the further up in the directory tree I'm going to move it. My directory tree tends to sort of mirror the levels of abstraction in the code . This doesn't match 100% and it's not always applicable, but that does sort of seem to be how things work, at least the way I end up structuring my code. The last folder that I will probably have is some sort of shared folder. At least I typically have that for components and hooks. It's a little bit different for other things, but maybe there's going to be a util folder for the server or something where I have really generic stuff that can be used all over the place. But if I find out that this is actually something that can be used by multiple packages or it really is very generic, then maybe I'll create an npm package, so to speak, in my monorepo. I'm going to be going over this when we reach the workspaces lesson, because we 're going to be using workspaces, which is sort of a way to create little npm packages in your repository. And then finally, if something is actually useful to others or I just feel like this is something I'm going to be using in more projects, then maybe I will end up creating an npm package, because then it's just so generic that it really should be published. It could be a private package, but I prefer to try to make things open source if that is possible. So from that perspective, I would argue that a monorepo is at least the obvious place to start. Even if you decide later on that it doesn't work for you for whatever reason, it is just the simpler solution to things, just having one place for everything. So why not start there and then split things up if you decide later on that it just doesn't work for you? There are some significant upsides to having everything in one place. For instance, it's much easier to share things like Linter settings and Type Script configurations. We're going to be looking at that in a following lesson. More importantly though, I would say that the fact that everything is synchronized, so for your services, they back in and front end or possibly other services if you have them, for them to be synchronized in say a branch makes it much easier to try out things that are requiring changes in both of those or more of those services. It's also easier for onboarding when you have a new team member, because there 's just one repo that they need to check out and they will have everything there. There are some downsides too as well. For instance, there's a higher risk of merge conflicts, which is obvious when you just have one repository, everybody's going to be working in that at the same time and there's a higher chance that there's going to be some conflict somewhere. But in my opinion, this is actually an expression of a conflict in the structure itself. And so if you didn't have it in the Monor repo, you would probably just be experiencing this in a more unpleasant way at runtime in one fashion or the other. There can be an issue with disk space if the repo grows very large. I know that both Google and Microsoft have solutions for this with actually doing something particular with Git. Not sure how that works, but this is something I have never experienced anywhere. So I think that's a very limited problem for most people. You may run into a situation where your lint two settings and TypeScript configurations and what else you have doesn't actually work for every project in the repo. And so maybe that shared thing loses its value. That's a potential, but that also seems like a very trivial thing to me. The last thing that could be breaking this is if you have some compliance rules . If one team is simply not allowed to work or see a piece of code, obviously that might create a tension for you. But we're going to assume here that there are no specific compliance rules. I don't think there would be for a booking system anyway. So we are going to use the mono repo and hopefully you will be able to as well.