使用pnpm workspace搭建monorepo

Yukino 1,181 2022-12-06

背景:之前的项目告一段落了,最近开始写一些组件库,主要是上面想统一现有系统的UI风格,所以写一些通用组件来节省时间,之前的私有npm也搭起来了,就开干了。

一、简介

monorepo是一种将多个项目存储在同一个存储库中的版本控制策略,对应到本篇要介绍的内容就是将多个npm package存储在一个git仓库中,这样做的优点有:

  1. 对于组件库来说可以不用每一个package都开一个新的Git库;
  2. package之间的引用可以不用发布、下载;

本篇使用的是pnpm的workspace来搭建monorepo。

二、创建项目

  1. 初始化项目:
pnpm init
  1. 在项目根目录创建pnpm-workspace.yaml,内容如下:
packages:
  - 'packages/**'
  - 'dev'

上面的意思就是dev目录和**packages下的子目录**均为一个package,然后创建对应的目录并初始化:

mkdir dev
mkdir packages
cd dev && pnpm init

我们在packages下创建一个hello目录并初始化用来作为我们要发布的一个包,dev目录作为我们的调试项目:

mkdir hello
cd hello && pnpm init

现在的目录结构应当如下:

├── dev
│   └── package.json
├── package.json
├── packages
│   └── hello
│       └── package.json
└── pnpm-workspace.yaml
  1. 安装依赖

对于pnpm的workspace依赖有两种,一个是workspace共用的依赖,另一个是独立package的依赖;

对于第一种workspace共用的依赖,比如我们可以安装typescriptvite到workspace:

pnpm i -w -D typescript vite

对于第二种独立package的依赖,比如我们安装vue到hello的package:

cd packages/hello
pnpm i -D vue
  1. 编写一个vue组件
cd packages/hello
vim index.ts
mkdir src
cd src
vim hello-wrold.vue

// index.ts
import HelloWorld from './src/hello-world.vue';
export {
  HelloWorld
}

// src/hello-world.vue
<script setup lang="ts">
interface Props {
  name: string;
}
const props = defineProps<Props>();
</script>
<template>
  <span>hello: {{ props.name }}</span>
</template>
<style scoped></style>
  1. 初始化dev调试项目
pnpm create vite
pnpm i
  1. dev安装hello依赖
pnpm i hello

安装后dev/package.json中会新增一条dependencies

{
  "name": "dev",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "hello": "workspace:^1.0.0", // 这个
    "vue": "^3.2.41"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^3.2.0",
    "typescript": "^4.6.4",
    "vite": "^3.2.3",
    "vue-tsc": "^1.0.9"
  }
}

接下来就可以直接在dev项目中使用hello了

// App.vue
<script setup lang="ts">
import { HelloWorld } from 'hello';
</script>
<template>
  <HelloWorld name="❄️"></HelloWorld>
</template>

项目代码已上传到github - main分支,可对照commit记录查看搭建过程。