参考文档
- pnpm pnpm.io/zh/pnpm-wor…
- monorepo的解决方案 www.zhihu.com/question/50…
- rush rushjs.io/zh-cn/pages… github.com/MFinnnne/ru…
Monorepo
Monorepo 是将多个包(package)统一放置在一个仓库(repo)进行管理的方式。这种方式可以更好地管理包之间的依赖与兼容,统一的提交日志也更容易追踪问题。许多大公司如 Google、Facebook 都采用 Monorepo 方式管理的多个前端包。
pnpm
pnpm 是一个快速、节省磁盘空间的包管理工具。它通过硬链接在 node_modules 中共享依赖,避免了重复安装同一个包的多个版本,这大大节省了磁盘空间。
Monorepo + pnpm
在 Monorepo 项目中使用 pnpm 具有以下优势:
- 空间节省:通过硬链接的方式,无需重复安装包,这在有许多包的 Monorepo 项目中特别有效。
- 依赖共享:不同包可以共享依赖,简化依赖管理,避免重复依赖的安装与升级。
- 统一依赖:pnpm 以锁定文件(pnpm-lock.yaml)来管理依赖版本,这可以促进 Monorepo 中的包采用同一版本的依赖。
- 快速安装:pnpm 通过硬链接,只需安装一次包,后续的安装会非常快速,这很适合 Monorepo 频繁开发与构建的场景。
使用者
许多知名公司和开源项目都采用 Pnpm + Monorepo 的方式来管理项目,比如:
- Babel:Babel 是一个广泛使用的 JS 编译器,它采用 Pnpm 和 Monorepo 来管理众多包和插件。
- React:React 这个至关重要的前端框架也是使用 Pnpm 和 Monorepo 构建的,它有上百个内部包需要管理。
- Vue:Vue 框架同样采用 Pnpm 和 Monorepo,以管理其众多工具、框架、UI 库等。
- Next.js:Next.js 这个流行的 React 框架也是采用 Pnpm 管理 Monorepo 的结构构建的。
步骤
电脑环境 node@16
安装 pnpm
npm install -g pnpm
// 查看对应的版本
pnpm -v
创建 workspace
pnpm init
根目录创建 pnpm-workspace.yaml 重要
packages:
# 公用依赖
- "pl-core/**"
# 各个项目
- "projects/**"
创建自己的目录结构
依赖独自分开暴露
├── libs
│ ├── core
│ │ ├── src // 含有一些apis
│ │ └── package.json
│ │ └── index.js // 对外暴露
│ ├── ui
│ │ ├── src // 一些ui组件
│ │ ├── package.json
│ │ └── index.js // 对外暴露
│ ├── util
│ │ ├── src // 一些工具类
│ │ ├── package.json
│ │ └── index.js // 对外暴露
├── projects
│ ├── p1 //实际的项目
│ │ ├── src
│ │ └── package.json
│ ├── p2 //实际的项目
│ │ ├── src
│ │ └── package.json
├── package.json //全局第三方公用包管理,如 axios element-ui
├── pnpm-lock.yaml
└── pnpm-workspace.yaml // 配置 项目+依赖的公用模块
依赖集中式对外暴露
├── pl-core
│ ├── src // 含有一些 apis utils components
│ ├── package.json // 默认暴露出口 index.js
│ ├── index.js // 对外暴露
├── projects //实际的项目
│ ├── p1
│ │ ├── src
│ │ └── package.json
│ ├── p2
│ │ ├── src
│ │ └── package.json
├── package.json //全局第三方公用包管理,如axios element-ui
├── pnpm-lock.yaml
└── pnpm-workspace.yaml // 配置 项目+依赖的公用模块
pnpm 常用指令
// 初始化项目 生成 package.json
pnpm init
// 添加依赖包
pnpm add [package.json的name]
// pnpm 查看源
pnpm config get registry
// 切换淘宝源
pnpm config set registry https://registry.npmmirror.com
// 全局依赖(供全局使用)
pnpm i element-plus -w
// 移除依赖
pnpm uninstall @libs/ui
根目录
技术选型后全局安装公用依赖
// 技术选型如 vue3 + vite + element-plus
// 根目录执行指令
pnpm i element-plus axios -w
创建 pl-core 核心模块
- 创建以及初始化
npm init vue@latest
npm i
npm run dev
- 在 src 编写 apis utils components
// /src/components/Count/index.vue
<template>
<p>count:{{ count }}</p>
<button @click="count++">点击我++</button>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
</script>
// /src/utils/sum.js
export const sum = (...rest) => rest.reduce((pre, cur) => pre + cur, 0)
- 新建
index.js对外暴露 apis utils components
// pl-core/index.js
import Count from "./src/components/Count/index.vue";
export { sum } from "./src/utils/sum";
export { Count };
新建 projects 目录,用来存放各个项目
- 1.创建项目(项目技术选型最好跟 pl-core 目录下的选型一样,譬如 axios 版本 vue 版本 element 版本)
npm init vue@latest
npm i
npm run dev
- 2.切换到 projects 对应的项目目录下,添加并安装 pl-core
重要
pnpm add [pl-core/package.json的name]
// 譬如
pnpm add pl-core
- 3.安装成功后,使用依赖
<template>
<div>
<h3>p1</h3>
<Count />
</div>
</template>
<script setup>
import { Count, sum } from "pl-core";
console.log("sum", sum(1, 2, 3));
</script>
- 4.针对 pl-core 导出组件时第三方样式丢失的问题,可以在引入的项目里添加对应的样式
构建产物
在projects/p1各个项目中构建,
npm run build
构建的产物中会自动包含有libs目录下的资源
http-server dist
一些方便操作
根目录 package.json 文件 配置 启动||构建 各个项目的指令
"scripts": {
"run:p1": "pnpm -F \"p1\" -r dev", //运行 projects/p1 项目中的package.json 对应的 dev 指令
"run:p2": "pnpm -F \"p2\" -r dev",
"build:p1": "pnpm -F \"p1\" -r build",
"build:p2": "pnpm -F \"p2\" -r build"
},