Create a Shared Library in a pnpm Workspace

Share this video with your friends

Social Share Links

Send Tweet

You can create private libraries in your monorepo that you can share between your other packages and applications.

To do this all you need to do is create a new folder containing a package.json in your packages directory. You can then use pnpm filter commands to add external libraries to your package without ever having to cd into it!

Then just make sure to create an entry point and set the main field in your package.json to where your code will compile when built.

Instructor: [0:00] Now that we have our remix app here hosted in apps folder, let's actually add a library in here, which we can then consume from our remix app. And so to get started, let me just create here a new package. Let's call it Shared UI for potentially hosting our shared UI components. [0:18] Let's create here, package.json. Let's copy in here a couple of things, slides. We could actually have as our license. Here we could just have...this is a private package because we don't intend to publish this to any npm registry. Its name is Shared UI, same as the folder. It doesn't have any scripts yet, but we'll add some and we can leave the rest out for now.

[0:41] Now, the next thing is we want to use actually a React library. That's what we want to create, and we want to use TypeScript for it. I want to install those packages. Now, I can obviously just go in here and add them to the dependencies or Dev dependencies, but we can also use the filter commands of pnpm to install them. We can, from the root level of the workspace, run PNPM add --filter, because we want to use them or add them to that shared UI library.

[1:09] I type here, I want to have React as a dependency, add it to that library in my PNPM workspace. As you can see, now we have that in our package JSON. Similarly, I want to have TypeScript but as a devDependency. Now I have both set up. I have React and I have TypeScript.

[1:29] To get started, let's add here a React component. Let me paste in some code for a potential Button component, which we are adding to our library here. Potentially, we might also want to have something like an index.tsx file, which is the entry point.

[1:45] Here we export all of the public parts that can be consumed by other parts within our monorepo. In this case, the Button is definitely something I would want to export. I do export * from my Button here, such as other parts and pieces of my monorepo. In this case, the React Remix application, at the very top, can import this and use that button in its application.

[2:09] There could totally be private pieces to that shared UI Library, which you wouldn't expose in that moment via that tsx file. In order for this Lyra to be able to be used by other parts of the monorepo, we also want to compile it.

[2:23] To keep things simple, I'm just using plain TypeScript compilation here. We could obviously use something like esbuild or SWC, or even ZAP for compiling our TypeScript setup here, but I'm going for a bare-bones TypeScript setup.

[2:39] Let's create a tsconfig.json inside our shared UI, which I'm pasting in here a couple of options.

[2:45] You can see, I specified out here to be a local disk folder. Let's also make sure in the package.json to configure it accordingly, such that, the main entry point here, which we don't have right now but we should add here, points to disk/index.js. That's basically where our output would be compiled.

[3:06] Another thing we want to add here is how I actually can build this library. In this case, I would have build command here that would probably delete my disk folder first. I would do something like tsc to compile the library based on the tsconfig that I'm having here.

[3:23] Note, if you have Windows where you don't have an rm command, you can install something like rimraf, which is an npm package, to do the same stuff, but I want to keep it simple. You feel free to change that on your machine if you need to.

[3:39] Now, with this setup again from the very root of our monorepo workspace, we can run something like pnpm --filter. The package will be shared to UI in this case, and I want to run the build command. This now runs the rm-rf/disk to remove the disk folder if it exists and then runs tsc to compile our button.js file in here.

[4:02] With this, our package is ready to be imported into our remix app.