pnpm + monorepo:高效的项目管理方式

pnpm + monorepo: 高效的项目管理方式

前言

在进行多项目管理时,一般有两种方式,multirepomonorepo

multirepo

multirepo 是将每个项目或者模块分别放在各自的 git 仓库里,需要对每个仓库单独维护。

项目架构如下:

zsh 复制代码
app/    # 项目A ([email protected]/app.git)
app2/   # 项目B ([email protected]/app2.git)
share/  # 公共模块 ([email protected]/share.git)

monorepo

monorepo 是将多个项目或者模块放在同一个仓库里,除了有公共的 packages.json 之外,每个项目都有自己的 packages.json

对应公共的依赖可以安装到公共的 node_modules 里,而每个项目的依赖则安装到各自的 node_modules 里,实现依赖共享

同时,每个子模块之间可以实现互相引用,而不需要发布成 npm 包,管理更加高效。

项目架构如下:

zsh 复制代码
- monorepo/
 - packages/
   - app/   # 项目A
   - app2/  # 项目B
   - share/ # 公共模块
- package.json

pnpm + monorepo

接下来讲一下如何使用 pnpm + monorepo 来进行多项目管理。

安装 pnpm

首先,全局安装 pnpm

zsh 复制代码
npm install -g pnpm

初始化 monorepo

创建一个 pnpm-monorepo 文件夹,然后通过 pnpm init 创建 package.json

zsh 复制代码
mkdir pnpm-monorepo
cd pnpm-monorepo
pnpm init
json 复制代码
// package.json
{
  "name": "pnpm-monorepo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

然后,创建一个 packages 文件夹,用来存放子模块。

我们在 packages 文件夹下创建两个子模块:appshare

对于app 模块,我们用 pnpm create vite app 创建一个 vue 项目。

zsh 复制代码
cd packages
pnpm create vite app
json 复制代码
// packages/app/package.json
{
  "name": "app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.5.13"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.2.2",
    "vite": "^6.3.1"
  }
}

而对于share 模块,我们用 pnpm init 初始化一个项目,然后新建一个 index.js 文件。作为入口文件,在里面暴露一个公共方法:

javascript 复制代码
// packages/share/index.js
function add(a, b) {
  return a + b;
}
export default { add };
json 复制代码
// packages/share/package.json
{
  "name": "share",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

配置 workspace

pnpm-monorepo 文件夹下,创建 pnpm-workspace.yaml 文件,配置子模块。

yaml 复制代码
# pnpm-workspace.yaml
packages:
  - 'packages/*' # 指定 packages 目录下所有模块都为 monorepo 的子模块

这个时候一个基本的 monorepo 项目架构就创建好了:

zsh 复制代码
- pnpm-monorepo/
 - packages/
   - app/   # vue 项目
   - share/ # 公共模块
 - pnpm-workspace.yaml
 - package.json

依赖管理

如果在根目录下 执行 pnpm install,会自动安装根目录和所有子包的依赖项。

如果我们想分别安装依赖,可以通过指定参数来控制。

安装公共依赖

公共依赖是每个子模块都会用到的依赖,我们可以安装到公共的 node_modules 里。

比如,我们的 vue 项目和 share 模块都依赖了 lodash-es 模块,那么就可以作为公共依赖安装。

通过添加 -w 参数,可以安装到根目录的node_modules 里。

-w--workspace-root 的简写。

zsh 复制代码
pnpm i lodash-es -w
安装子模块依赖

子模块自己用到的依赖可以安装到各自的 node_modules 里。

比如,只有 vue 项目里用到了 axios 模块,那么就可以安装到 app 项目的 node_modules 里。

通过 --filter <package-name> 参数,可以指定安装到哪个子模块的 node_modules 里。

--filter 可以简写为 -F

注意,这里的 package-namepackage.json文件中的 name 字段。

zsh 复制代码
pnpm i axios --filter app

模块共享

如果我想在 vue 项目里引用 share 模块的 add 方法,需要将 share 模块安装到 app 项目的 node_modules 里。

可以通过 --workspace 参数,告诉 pnpm 去当前 workspace 查找相关模块。

zsh 复制代码
pnpm i share --filter app --workspace

这时 app 项目的 packages.json 文件就会多一个 share 模块的依赖。

json 复制代码
...
"dependencies": {
  "share": "workspace:^",
  "vue": "^3.5.13"
}
...

其中,workspace 表示当前工作空间,^ 表示安装最新版本。

也可以通过在 package.json 的依赖里声明 "share": "workspace:^",也可以指定具体的版本号。这样在安装时就不需要添加 --workspace 参数了。

如果想把 share 模块作为公共依赖安装的话,在后面再加一个 -w 参数就可以了。

zsh 复制代码
pnpm i share --workspace -w

总结

  • pnpm i :安装所有的依赖,包括公共依赖和子模块依赖。
  • pnpm i -w :安装公共依赖到根目录的 node_modules 里。
  • pnpm i --filter <package-name> :安装指定子模块的依赖到 node_modules 里。
  • pnpm i <package-name1> --filter <package-name2> --workspace :安装当前 workspace中的模块到指定项目的 node_modules 里。
  • pnpm i --workspace -w :安装当前 workspace中的模块到根目录的 node_modules 里。
相关推荐
shenyan~2 分钟前
关于 js:9. Node.js 后端相关
前端·javascript·node.js
uwvwko17 分钟前
ctfshow——web入门254~258
android·前端·web·ctf·反序列化
所待.38327 分钟前
深入解析SpringMVC:从入门到精通
前端·spring·mvc
逃逸线LOF1 小时前
CSS之精灵图(雪碧图)Sprites、字体图标
前端·css
海天胜景2 小时前
jqGrid冻结列错行问题,将冻结表格(悬浮表格)与 正常表格进行高度同步
前端
清风细雨_林木木2 小时前
解决 Tailwind CSS 代码冗余问题
前端·css
三天不学习3 小时前
VueUse/Core:提升Vue开发效率的实用工具库
前端·javascript·vue.js·vueuse
余道各努力,千里自同风3 小时前
CSS实现文本自动平衡text-wrap: balance
前端·css
Yvonne爱编码3 小时前
CSS- 4.3 绝对定位(position: absolute)&学校官网导航栏实例
前端·css·html·html5·hbuilder
繁依Fanyi4 小时前
ImgShrink:摄影暗房里的在线图片压缩工具开发记
开发语言·前端·codebuddy首席试玩官