Lesson Description

The "Monorepo Project Tour" Lesson is part of the full, Enterprise UI Development: Microfrontends, Testing, & Code Quality course featured in this preview video. Here's what you'd learn in this lesson:

Steve walks through the monorepo project codebase, which highlights how to manage multiple microfrontends or packages in a simplified workflow that avoids multiple repos. He highlights the use of workspaces in package managers such as npm, pnpm, and Bun to manage dependencies within the repo.

Preview

Transcript from the "Monorepo Project Tour" Lesson

[00:00:00]
>> Steve Kinney: And this is the repo that we're going to use for the rest of the day. Days plural. And effectively, it can be built because we know that micro front ends and poly repos don't have to be the same. So we'll start out with this idea of we'll have one repo for our own sanity because also, I don't have a lot of beliefs, so one is that more repos, more problems. One more GitHub workflow I gotta update. One more like set of packages, one more place to find pull requests or issues that I'm running an open source library.

[00:00:39]
I am reluctant to make more repos than I need to personally, but you might have a different setup. So let's look at the beginnings here, because it's not a lot of code to write, because it's fundamentally the same app, to be clear. If I spin it up, it's going to be, except instead of spinning up two servers, I'm going to spin up one server this time, because again, they're all getting built as one app, despite the fact that they live separately from each other.

[00:01:06]
So I'm going to kill this app off. I'm going to go back into that other one and spin it up, but we're going to look at this in the GitHub UI. Enterprise UI Workshop. I'll do pnpm run dev. That's a fun thing I'm going to do in a second. You should spell install correctly if you're going to run it, do it, by the way. If you don't install dependencies, your code doesn't work. Fun fact. Great. And so this is now one port.

[00:01:46]
There's no 3000, 3001. Before I was using rspack, this time I'm using Vite. Mostly as an exercise to show you how little of a difference it makes, and that none of this stuff, I'm trying my hardest other than how to be written in something to keep it as language agnostic as possible. And here we have, okay, a slightly more robust version of the previous one. So we've got the analytics, we've got the users, and we've got the settings in this case, right?

[00:02:17]
So we're going to treat those as our three micro applications at this point. And then we've got the shell. So, effectively all it really is, is an expanded version of what we were working on previously. But this time they all live in one repo, one dev server, right? We'll move, this is kind of walking a fine line between monorepo and micro front ends, but like, it's cool. And we'll kind of just see the difference, we can pick the flavor.

[00:02:48]
Because again, if this was multiple repos, the only additional step is you figuring out how to either clone down those other repos, install those other repos and npm packages. It's just how you choose to like break it up and put it back together, but they will eventually have to come together in this case. So we just saved ourselves from some of that. And we'll go ahead and we'll open this one up in code.

[00:03:12]
And we'll take a tour. So before we had the host, we had the shared, we had the remote. Now we kind of have a slightly different concept here where we have this idea of apps, right, where we'll have a legacy codebase when we talk about migrations. At another point we've got the dashboard and we've also got these packages which are, that users you saw before, the analytics, which was our remote package before the shared stuff, some of the UI components, so on and so forth.

[00:03:47]
When we talk about workspaces, I have a whole write-up because npm has a concept of workspaces. Pnpm has a slightly more improved concept of workspaces that is easier to work with. Bun has a concept of workspaces, which is exactly like pnpm's. It doesn't matter. It doesn't matter. These are approaches, not necessarily technologies that you need to like memorize, but the important part is that, you know, we've got the main package.json for the overall app.

[00:04:25]
And if you were doing this in npm or Bun, you would define them in your package.json. In pnpm, it goes into a YAML file next to your package.json, right? Part of the reason was to be able to look at this separately. And so we have this idea of packages and packages are just other package.json based things. Again, they could be in other repos, they could be in the same repo, it doesn't matter, and these are places so that when you say import or require, right, it knows places within to look, right before it goes to hit npm immediately, right?

[00:05:09]
And so we say, hey, we have a bunch of packages, a bunch of different front ends in this repo, you can find them in apps, packages, some other stuff we'll talk about tomorrow. Make believe these are the only two that exist right now. Those other two will be important later. And so, like I said, apps, we've got the current, the dashboard, and then the legacy one, in packages, we've got, you know, UI has got what you think it does is our baby's smallest design system.

[00:05:42]
The analytics is that dashboard you saw earlier. The users, you know, you can kind of poke around, it's the user list that we saw at a different point as well. And all of that is in there too. And what's cool is you, if you look at we've got shared, I am mostly writing it as if it was on npm. Now it's not. If I go into shared, you can see there is a package.json as if this was its own repo, and it could be, it doesn't matter how you assemble this thing doesn't really matter.

[00:06:22]
And it's like, it says @pulse/shared. If we go into the UI, we look at that package.json, each one of these is effectively a small little front end package, right, that just looks like your everyday npm package. It's got its own build scripts. It is, if you've ever used npm before, it's everything you know and love. This won't go looking at npm because as you can see, shared analytics, UI, and users are in this packages folder.

[00:06:59]
Dashboard is in this apps folder. Go back to the pnpm workspace. We say, where, we've got packages hiding in apps, and we've got packages hiding in packages. Those names are not meaningful. Right, I could have changed these to like burrito and sushi roll, right, and it doesn't matter. It's just going to say, hey, I'm going to look for these somewhere around there. There is one other piece that I alluded to before, and we can see it if we go into the apps under the dashboard, which is when we look at the versions.

[00:07:33]
Right, so like React. I apparently stuck with using the old version of React because I copied the one project into this project to start it, but you know, whatever, we can bump it to 19 if we want. It's not a React course, I don't care. But if you look at @pulse/ui, @pulse/shared, @pulse/analytics, those all say workspace colon star. And that's basically when we do an npm install, it's not going to go to npm.

[00:08:05]
It's going to say, hey, you told me where all the other packages are in this workspace. I'm just going to go grab it from over there and install it. Right. So if you were to do this by curling a bunch of stuff together, right, and building your like, shell that way, great. If you want it, like, then you can fully have this be polyrepo. If you wanted to keep them all in the same repo, be a single repo, multiple front ends, this will work as well.

[00:08:36]
And there's a few caveats here, right? There's a bunch of ways that I'm cheating right now to make this easy, and I call them out now because we're going to have to solve them eventually, which is, by virtue of the fact that this is almost all React code. In this case, being bundled by Vite, and I will go look at the Vite config. Because we don't have all the module federation stuff that we had before.

[00:09:10]
But if you go back and look at the rspack config. And you go back and you look at the Vite config, they're basically the same, right? And one of the nice parts is one thing that Vite does, and a lot of other build tools is that they will transpile TypeScript. Which means I don't have a build step. The problem that we're going to have to solve in the next section, if I can do some foreshadowing, is what would happen if, like, I think about this like SvelteKit, for instance, the svelte.config.js only takes JS.

[00:09:49]
So if I had a bunch of like plugins, I have to transpile them all to JavaScript from TypeScript before I could like import them, right? And so the big question we have is like, it seems really great to say, workspace star, but like, what if I had to compile all these first? Right. And imagine they weren't all going into one shell, but imagine like, and it is actually true, that all those UI components were actually used in some of the other UI pieces, right?

[00:10:24]
So now you also have not only you need to compile things first. You also need to do it in a particular order. And that is like where the strategy gets really hard because then like, are you going to write a custom script that says, okay, what I need you to do first is I need you to transpile all the TypeScript and like, even like Svelte, for instance, like, you know, that's a .svelte file needs to get turned into JavaScript.

[00:10:56]
.tsx maybe needs to get turned into .jsx which needs to get turned into .js, so on and so forth, right? Like, do you say, okay, first do this one. And then do shared. And then do analytics, users, oh, but do we need to run the test first? So how does that play out, right? And this is where that, you know, complexity comes in. The only takeaway from, you know, talking about the build time configuration in this case is that there's less to do than the runtime micro front ends because you're not setting up all that like, what do I, what do I fetch remotely and what do I have?

[00:11:39]
You're kind of just using npm as it is. The trade-offs are pretty straightforward. The point of kind of talking about this one is to point out it is on one hand simpler than the module federation, because it's just regular npm. It does have its caveats, but like where it introduces the concepts of what we think about with monorepos of like how do you build stuff in the right order and like in this case, on the, if we just deployed this as it is today, we'd have another problem, which is, let's say.

[00:12:19]
I've got like a robust test suite. Right? And it's got like 1000 Playwright tests. Good, good on us. Look at that, we're great. And let's say that you make a CSS change. We're going to run all of them. We're going to run every single test. Your team's, my team's, everyone's teams, right? We're running everyone's teams tests and like, that's terrible, right? So like, this works. And in simple cases, it's great.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now