Lesson Description

The "Setup pnpm Workspace & Scripts" Lesson is part of the full, TypeScript Monorepos: Architect Maintainable Codebases course featured in this preview video. Here's what you'd learn in this lesson:

Mike demonstrates setting up a new package in a monorepo by creating a folder, moving code, configuring package JSON, adding scripts, and preserving git history. He highlights pnpm for its readable lock files and smooth restructuring.

Preview
Close

Transcript from the "Setup pnpm Workspace & Scripts" Lesson

[00:00:00]
>> Mike North: So the first thing we're going to do is we want to create a folder for this new package. So we're going to say mkdir dash p. So we create all subfolders necessary to make this work. And we're just gonna call this UI. I'm creating a folder here called Packages.

[00:00:18]
This is where I'm going to put all of my packages. There's another approach that some people like to take here where they'll have two folders, one called Apps and one called Libraries. And they'll separate out their leaf level dependencies like CLIs, UIs, servers from things that are sort of in the middle of the dependency graph.

[00:00:39]
But it's just purely an organizational construct and we're going to keep things simple for now. All right, next we're going to take all of the code and except for a couple files, if you're following the course notes, I have this list of files too. We're going to select everything, deselect packages.

[00:01:02]
What we're going to leave is the gitignore, the nvmrc which is just make sure we're all using the same node version. We're going to leave the prettier config, we're going to leave the pnpm lock file. We're going to leave the readme for the whole project and let's move everything into,
>> Mike North: Let's move everything into packages UI except for those things.

[00:01:37]
Okay, I'm definitely hit no here. This is gonna freak havoc if you update imports for known modules. The next thing we'll do and I think I actually had a version of this I accidentally checked in here, but, no, no, this is fine. PNPM workspace. You want to have this also in your root level.

[00:02:03]
Now I've added some things here. Normally when you'd start this journey you wouldn't have this file. All we're seeing here is these files, sorry, these NPM modules have a post install step that requires like a little bit of a build once it's installed and it's on disk. And this allow lists those two packages so that they can do their post build step.

[00:02:26]
Normally you'd be blocked and you'd see a message and it'd say like, do you wanna let these two things run? So I've taken care of that for you. But the meaningful thing we have to add to this pnpm workspace YAML file is this packages and then we're going to say, we're going to in packages, say packages.

[00:02:53]
What we're saying here is we're telling pnpm that this is where it can look for subfolders, each of which represents a package. Now we will need. So if we close up packages UI, we're going to need a package JSON at the top level of the project. This is going to be really thin.

[00:03:17]
We're going to give this package a name and it's going to be called Seeds, and we're going to give it a version and we'll just say 001 and we can say it's private. True, what private means is your package manager will refuse to publish this to NPM if it's private.

[00:03:40]
And there's one more thing that I want us to move here, and that is if you go to your package JSON you'll see there's a little volta object at the bottom. This is kind of like the nvmrc, just make sure that if you have volta installed, we're all using the same version of Node.

[00:03:53]
This only really matters, or at least using a monorepo the right way, in my opinion. You'd say we want one version of Node that you're using across development of every single thing in this repo. So I wanna cut that, bring it to our root level package JSON, paste it, and save.

[00:04:14]
One last change we have to make, if we go back to our UI package JSON, the one with all the dependencies in it, we're gonna wanna rename this. Originally this was the Seeds package project and we're going to rename it to this. Now, what I've done here is I'm kind of leaning into this concept of NPM scopes.

[00:04:37]
So if you wanted to put this on NPM, if I wanted to publish this project, I could go and reserve, if it's available, the NPM scope seeds. And that means this is kind of a prefix that I can use for any packages that I wish to publish. So, for an open source monorepo consisting of TypeScript libraries, it's very, very common for you to have an NPM scope that kind of says it's sort of in the package registry.

[00:05:05]
The monorepo concept, it's saying these are all interrelated packages for some reason. Sometimes they're used for other things too, like Stripe. We have a ripe scope, and we have multiple repos, but it's sort of an indicator that this is a real package from Stripe or some of our real packages are there.

[00:05:31]
Great, okay, this is gonna be a recurring theme. I've touched some package JSON files. Therefore, I must run pnpm i. Before we do, I just want us to examine the state of the world. There's no node_modules folder anywhere here yet. There is one, of course, here, it was part of what we dragged.

[00:06:00]
We should see a little node modules folder up here now. It's not very interesting. There's not much in here yet, but we will get there. You can see that there's some evidence of something's happening. Like, hey, look, this is a little a state file. And we've recognized that there is this package.

[00:06:21]
And I have 001 here. Clearly something's taking place. Now, something unfortunate's happened here, though. What I wanted to do was say this still works and the build command's not found. We have to figure out a way to wire this up. The solution to this is going to be going back to this package JSON file@ the root of the project, and we're going to be creating some scripts.

[00:06:52]
The first script we're going to create is this build pnpm color run dash r build. I'm writing this in the most explicit way possible so that we can see how this works. Now, if we were to run PNPM build, we can see, hey, look, there's Vite doing its thing, and it's building the project.

[00:07:18]
What does this mean? Well, first we're saying I'm running this build task and I'm doing so recursively. I am going into each package that I find in the workspace as defined in this workspace YAML file. Like I'm going to everything I find here. And by the way, this is how you do multiple oops, except with real YAML.

[00:07:47]
Well, you have multiple listings here. I think you just can't have the same thing over and over. But like it's going through every package that, that it can find and where a build task exists. Like, as long as a package, like our UI project has some build script that is going to be run, all this does is make sure that the colorful output is preserved to get everything wired up nicely.

[00:08:17]
It's gonna be super easy. We're going to create a bunch of these. We're going to say this one is lint and this one is test and this one is dev and this one will make format and last one is check. Again this snippet is in the course notes, if you want to make that real easy.

[00:08:49]
But it's just like, we haven't really changed what any of these things mean. We have simply now said all right, there's a fan out for all of our one packages. We're going to run these things now. You should be able to do pnpm test and it should work pnpm lint and it should work pnpm dev.

[00:09:17]
We should see the startup where there's the client, there's the server, everything works well.
>> Mike North: One more thing I want to show you all that's important about how we just did this. Let's look at our git diff and let's add everything, and sorry, I can get rid of that.

[00:09:44]
I want to see this as a tree so that I can close the tests. In fact, the whole UI package. So look at what's happened here. We have a PNPM lock file because we preserved this because we didn't just sort of like nuke it or leave it in the UI sub package.

[00:10:06]
All that's happened here is like a little bit of restructuring up at the top. And there are obviously about 5,000 lines that haven't been touched. Very important. This is one of the benefits of pnpm. The lock files are much more human readable. And if you had done this with a YARN lock file or a package lock JSON, you might not see such a clean result here.

[00:10:32]
That would give you confidence. We have accomplished this reorganization of our code without releasing any of the locks that we had on all of our packages. You don't want to be doing that at the same time you're reorganizing your code. Because that's like we're trying to do one thing here, and that's move some files around and get some NPM scripts wired up.

[00:10:54]
That's nice. Then furthermore, if we look at the way that this code is being treated, it's important at this step. You want to see all of the changes you've made as being regarded as a rename. Why is having this as a rename a good idea as opposed to a deletion and an ad, which you would get if I was messing with these files, if I was making changes in the files of a substantive nature, in addition to making this move, you get to preserve your git history.

[00:11:28]
>> Speaker 2: That's right.
>> Mike North: Right? You don't want the old history of this file to end and then a deletion happens and then a new file pops up into existence and there goes your git blame because you've lost all of that history. It's very valuable to preserve. And so this is why when you're doing this step, I would advise this is a good first step to do.

[00:11:53]
Don't continue refactoring here and separating things out into different packages as part of that. Because when you're doing that, you're introducing a much stronger possibility that you're gonna lose history on some of these files. Well, in this case, it's such a simple operation we're performing that you've got a very good shot at these all just being sort of a reorganization, which is exactly what you're doing.

Learn Straight from the Experts Who Shape the Modern Web

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