Set up a monorepo using pnpm workspace

In the previous article, we discussed how a monorepo structure could be package-centric or app-centric, depending on your project needs. Well, in this particular article, we will set up a monorepo using pnpm and take the app-centric route.


This content originally appeared on DEV Community and was authored by Ukpai Chukwuemeka

In the previous article, we discussed how a monorepo structure could be package-centric or app-centric, depending on your project needs. Well, in this particular article, we will set up a monorepo using pnpm and take the app-centric route.

Image description

What's Pnpm? 

Pnpm is a new generation of package management tools; it works just like NPM and yarn but offers some advantages.

## install pnpm
npm install -g pnpm # install pnpm globally

Create a new directory or clone an existing repository

mkdir monorepo # creates a new folder

or

git clone repository-link # clones a git repository (note: replace the link with repository URL)`

Let's change our current directory to the recently created directory or cloned repo.

cd monorepo # change directory

Next, we are going to initialize the package manager with pnpm.

pnpm init

Optional: Initialize git if the directory wasn't cloned from GitHub or GitLab.


git init # initializes git
touch .gitignore

Add node_modules and common build output folders to exclude pushing them to your repository.

# .gitignore  

node_modules  
dist  
build
.env

Once all this is done, you can open your folder in your favorite code editor. If you use Visual Studio Code, you can open up the folder by using the command below

code . # opens up the folder in vs code

code . didn't work fix here

Set up the workspace

To set up a workspace, create a new file pnpm-workspace.yaml

touch pnpm-workspace.yaml # creates a new file 

Add the configuration below to the workspace file:

# pnpm-workspace.yaml

packages:
 - 'apps/*'
 - 'packages/*'

This configuration tells pnpm that your workspace includes all directories in the apps and packages folders.

Create the apps and packages directory

mkdir -p apps packages

We will break down our apps into two apps/website and apps/api.

**apps/website **The website directory, which we will configure using NextJS. To configure this, we need to change our current working directory to apps.

cd apps

pnpm create next-app website

apps/api The api directory, which we will configure using NestJs.

# monorepo/apps (current working directory)

nest new api --package-manager=pnpm # creates a new NestJS project

Create a Shared UI Library

Great job! You have got your apps set up. Now, let's take things to the next level by creating a shared UI library. This is where the magic of monorepos starts to shine.

packages/library The library directory will contain our shared UI components.

# monorepo 

cd packages 
mkdir library && cd library && pnpm init
# monorepo/packages/library/package.json 
{
  "private": true,  
  "name": "library",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Note we declare it as private by setting privateproperty to true; this is because we don't want to publish it to NPM or somewhere else, but rather just reference and use it locally within our workspace.

In our library folder, we will install the following: React as a dependency and TypeScript as a development dependency.

# monorepo

pnpm add --filter library react  
pnpm add --filter library typescript -D

The --filter library in the installation command, tells pnpm to install these NPM packages locally to the library package.

To keep things simple, we will make use of the TypeScript compiler to compile our package. We could have a more comprehensive arrangement for bundling numerous files together, using something like Rollup or Vite.

To use the TypeScript compiler, we are going to create a tsconfig.json file at the root of our library directory and add the configuration below.

# monorepo/packages/library/tsconfig.json 
{  
  "compilerOptions": {  
    "jsx": "react-jsx",  
    "allowJs": true,  
    "esModuleInterop": true,  
    "allowSyntheticDefaultImports": true,  
    "module": "commonjs",  
    "outDir": "./dist"  
  },  
  "include": ["."],  
  "exclude": ["dist", "node_modules", "**/*.spec.ts"]  
}

Next, we will update the package.json file main property to match the output directory specified in tsconfig.json and also add a build script.

# monorepo/packages/library/package.json 
{
  "private": true,
  "name": "library",
  "version": "1.0.0",
  "description": "",
  "main": "dist/index.js",
  "scripts": {
    "build": "rm -rf dist && tsc"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^18"
  },
  "devDependencies": {
    "typescript": "^5.5.4"
  }
}

Creating our first shared library UI component

Let us create a simple select component first Create the file in our library directory.

# monorepo/packages/library 

touch Select.tsx
# monorepo/packages/library/Select.tsx 

function CustomSelect(props: any) {  
   return <select onChange={(e) => props.onChange(e)}>
            {props.children}
          </select>;  
}

export default CustomSelect;

We also want to have a public API where we export components to be used outside of our library package. To achieve this, we will create an index.tsx file and export the Select component we just created.

# monorepo/packages/library 

touch index.tsx
# monorepo/packages/library/index.tsx 

export * from './Select';

Building our library

pnpm --filter library build

Consuming our library package from the NextJs app

Congratulations! You just created your own shared UI library component. To use this library inside our NextJS app in the apps directory, you can add it using pnpm or manually.

pnpm add library --filter website --workspace

This adds the library package as a website dependency

{
  "name": "website",
  "version": "0.1.0",
  "private": true,
  ...,
  "dependencies": {
    "library": "workspace:*",
    ...
  },
  "devDependencies": {
    ...  
  }
}

We are almost done. Let us update the library dependency value to "workspace:*". This means we want to resolve the package locally rather than from a registry like NPM, and * means we want to always use the latest version.

Now to use our Select Component, all we have to do is import it.

Start up the development server to see the component in action.

pnpm --filter website dev

Setting up scripts for the monorepo

In our root package.json file, we are going to add some scripts to make our workflow easier.

# monorepo/package.json

"scripts": {
 "dev": "pnpm run - parallel - filter \"./apps/**\" dev",
 "build": "pnpm run - recursive - filter \"./apps/**\" build",
 "test": "pnpm run - recursive - filter \"./apps/**\" test",
 "lint": "pnpm run - recursive - filter \"./apps/**\" lint"
}

Congratulations! We did it. This process shows how to set up a monorepo using pnpm. For a real project, I would recommend using any of the monorepo tools available; I mentioned a few in my previous post. They offer some advantages over pnpm.

GitHub Repository


This content originally appeared on DEV Community and was authored by Ukpai Chukwuemeka


Print Share Comment Cite Upload Translate Updates
APA

Ukpai Chukwuemeka | Sciencx (2024-09-05T18:40:16+00:00) Set up a monorepo using pnpm workspace. Retrieved from https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/

MLA
" » Set up a monorepo using pnpm workspace." Ukpai Chukwuemeka | Sciencx - Thursday September 5, 2024, https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/
HARVARD
Ukpai Chukwuemeka | Sciencx Thursday September 5, 2024 » Set up a monorepo using pnpm workspace., viewed ,<https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/>
VANCOUVER
Ukpai Chukwuemeka | Sciencx - » Set up a monorepo using pnpm workspace. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/
CHICAGO
" » Set up a monorepo using pnpm workspace." Ukpai Chukwuemeka | Sciencx - Accessed . https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/
IEEE
" » Set up a monorepo using pnpm workspace." Ukpai Chukwuemeka | Sciencx [Online]. Available: https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/. [Accessed: ]
rf:citation
» Set up a monorepo using pnpm workspace | Ukpai Chukwuemeka | Sciencx | https://www.scien.cx/2024/09/05/set-up-a-monorepo-using-pnpm-workspace/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.