[Monoepo] Creating a Monorepo with PnPM

2024-04-13 hit count image

Let's see how to create a monorepo using PnPM, one of the NodeJS package managers.

Outline

In this blog post, I will introduce how to create a monorepo using PnPM.

Blog Series

This blog is a series. Please check other blog posts through the following links.

PnPM

PnPM is one of the NodeJS package managers, and it is similar to NPM and Yarn. PnPM emphasizes fast installation speed and space saving. It is used in various projects.

install PnPM

You can install PnPM using the following command.

pnpm -v

If PnPM is not installed, run the following command to install PnPM.

npm install -g pnpm

Example

After installing PnPM, let’s use PnPM to create a monorepo. To create a monorepo, create the following folder and file structure.

.
├── package.json
└── src
    ├── module-a
    │   ├── index.js
    │   └── package.json
    └── module-b
        ├── index.js
        └── package.json

The package.json file of the module-a is as follows.

// src/module-a/package.json
{
  "name": "module-a",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  }
}

The package.json file of the module-b is as follows.

// src/module-b/package.json
{
  "name": "module-b",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  }
}

And, the index.js of the module-b is as follows.

// src/module-b/index.js
console.log('module-b');

Finally, the index.js of the module-a is as follows.

// src/module-a/index.js
console.log('module-a');

require('module-b');

After configuring the files like this, run the following command to check if the module is loaded correctly.

node src/module-a/index.js

Then, you can see the following error.

module-a
node:internal/modules/cjs/loader:1073
  throw err;
  ^

Error: Cannot find module 'module-b'
Require stack:
- /Users/deku/temp/temp/src/module-a/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1070:15)
    at Module._load (node:internal/modules/cjs/loader:923:27)
    at Module.require (node:internal/modules/cjs/loader:1137:19)
    at require (node:internal/modules/helpers:121:18)
    at Object.<anonymous> (/Users/deku/temp/temp/src/module-a/index.js:3:1)
    at Module._compile (node:internal/modules/cjs/loader:1255:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/Users/deku/temp/temp/src/module-a/index.js' ]
}

pnpm-workspace.yaml

To create a monorepo using PnPM, you need a pnpm-workspace.yaml file. Create a pnpm-workspace.yaml file in the root folder and modify it as follows.

packages:
  - 'src/*'

Install dependencies

module-a uses module-b, so you need to add module-b as a dependency in the package.json file of module-a. To add a dependency, open the src/module-a/package.json file and modify it as follows.

{
  "name": "module-a",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "module-b": "workspace:*"
  }
}

After modifying the package.json file, install the dependencies by running the following command in the root folder.

pnpm install

After then, when you check the folder structure, you can see that a Symlink to module-b is created in the node_modules of module-a.

.
├── node_modules
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── src
    ├── module-a
    │   ├── index.js
    │   ├── node_modules
    │   │   └── module-b -> ../../module-b
    │   └── package.json
    └── module-b
        ├── index.js
        └── package.json

For more information about Symlink, please refer to the following link.

Check

Now that you are ready to use PnPM for the monorepo. Run the following command to check if the modules are loaded correctly.

pnpm module-a start

Then, you can see the following output.

module-a
module-b

You can use the following command because a Symlink to module-b is created in the node_modules of module-a.

node ./src/module-a

module-b has no dependencies, so you can run the following command without any problems.

pnpm module-b start
# module-b
node ./src/module-b
# module-b

Completed

Done! We’ve seen how to create a monorepo using PnPM. If you are using PnPM instead of Yarn, please refer to this blog post to create a monorepo using PnPM.

Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!

App promotion

You can use the applications that are created by this blog writer Deku.
Deku created the applications with Flutter.

If you have interested, please try to download them for free.

Posts