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 里。
相关推荐
局外人LZ3 分钟前
前端项目搭建集锦:vite、vue、react、antd、vant、ts、sass、eslint、prettier、浏览器扩展,开箱即用,附带项目搭建教程
前端·vue.js·react.js
G_GreenHand18 分钟前
Dhtmlx Gantt教程
前端
鹿九巫19 分钟前
【CSS】层叠,优先级与继承(四):层叠,优先级与继承的关系
前端·css
卓怡学长21 分钟前
w304基于HTML5的民谣网站的设计与实现
java·前端·数据库·spring boot·spring·html5
宝拉不想努力了23 分钟前
vue element使用el-table时,切换tab,table表格列项发生错位问题
前端·vue.js·elementui
YONG823_API28 分钟前
深度探究获取淘宝商品数据的途径|API接口|批量自动化采集商品数据
java·前端·自动化
鱼樱前端28 分钟前
前端必知必会:JavaScript 对象与数组克隆的 7 种姿势,从浅入深一网打尽!
前端·javascript
小希爸爸1 小时前
1、中医基础入门和养生
前端·后端
神仙别闹2 小时前
基于VUE+Node.JS实现(Web)学生组队网站
前端·vue.js·node.js
下雨的Jim2 小时前
前端速成之——Script
前端·笔记