Building Vue3 Component Library from Scratch #2 Monorepo
Tags: vue
Published: 2024-05-18 10:38:16

This article is the second part of the series "Building Vue3 Component Library from Scratch". In this part, we will guide you through setting up a simple Monorepo project using pnpm, and we will complete package linking and testing.

## What is Monorepo

It's actually quite simple: Monorepo is a single code repository that contains multiple projects. Although these projects are related, they are logically independent and can be maintained by different people or teams.

## Why Use pnpm

pnpm is very convenient for package management, especially for a Monorepo project. For our upcoming component library development, there may be multiple packages that need to be linked and tested locally. pnpm supports this naturally. Other package management tools like yarn and lerna can also achieve this, but they are relatively more cumbersome. pnpm has become quite mature now, and popular component libraries like Vant and ElementUI are using pnpm. Therefore, we will use pnpm as the package management tool for this project.

## Setting Up pnpm

`npm install pnpm -g`

## Initializing the Project

Execute `pnpm init` in the root directory of the project. This command will automatically generate a package.json file.

```javascript
{
  "name": "stellarnovaui",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```

create file .npmrc in the root direcotry

```
link-workspace-packages = true
prefer-workspace-packages = true
recursive-install = true
```

## Package Management

Create a packages folder in the project root directory to store our various packages. Suppose we have package a and package b. Create subdirectories a and b under the packages directory (for testing pnpm's local referencing). Then, execute `pnpm init` in both the a and b directories to initialize them.

You will need to modify the package names. Change the name field to @stellarnovaui/a to indicate that this a package belongs to the stellarnovaui organization. Remember to log in to npm and create an organization (e.g., stellarnovaui) before publishing. Here is an example package.json for package a:

```javascript
{
  "name": "@stellarnovaui/a",
  "type": "module",
  "version": "0.0.5",
  "main": "index.js"
}
```

Here, our package `a` represents a utility package, and the `main` property in `package.json` specifies the entry point of the package, which is `index.js`.

Therefore, create `index.js` file in the `a` directory. This file will serve as the entry point for the package.

```javascript
export default () => {
    console.log("This is package @stellarnovaui/a");
};
```

Next, create an `index.js` file in the `b` directory and reference package `a` in it.

```javascript
import sayHello from "@stellarnovaui/a";
sayHello();
```

We used package `a`, so we need to install `a` first. In the `b` directory, run `pnpm add @stellarnovaui/a`. Clearly, this will result in an error because we haven't linked the two packages yet. So, how do we link them? It's actually very simple.

Create a pnpm workspace file `pnpm-workspace.yaml` in the root directory to link the packages.

```
packages:
  - packages/*
```

This means that all packages under the `packages` directory are now linked. Then, run `pnpm add @stellarnovaui/a` again.

Note that we used the ES6 import syntax, so we need to add the field `"type": "module"` in the `package.json` files of both package `a` and package `b`.

We will notice that a symlink to package `a` has appeared directly in the `node_modules` directory of package `b`. Additionally, the dependencies field in the `package.json` of package `b` now includes `"@stellarnovaui/a": "workspace:^"`. This indicates that it has been linked to the local `@stellarnovaui/a` package.

At this point, execute the following command in the b directory:

```
node index.js
```

Now we have completed the local package linking. This makes testing packages much more convenient in the future.

The final source code: https://github.com/markliu2013/StellarNovaUI