DEV Community


Posted on • Updated on

Building Vue3 Component Library from Scratch #2 Monorepo

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.

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

create file .npmrc in the root direcotry

link-workspace-packages = true
prefer-workspace-packages = true
recursive-install = true
Enter fullscreen mode Exit fullscreen mode

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:

  "name": "@stellarnovaui/a",
  "type": "module",
  "version": "0.0.5",
  "main": "index.js"
Enter fullscreen mode Exit fullscreen mode

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.

export default () => {
    console.log("This is package @stellarnovaui/a");
Enter fullscreen mode Exit fullscreen mode

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

import sayHello from "@stellarnovaui/a";
Enter fullscreen mode Exit fullscreen mode

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/*
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

The final source code:

Top comments (0)