vue3 + pnpm 打造一个 monorepo 项目
Monorepo 和 Multirepo
单一库房(Monorepo)架构,能够理解为:运用单一库房来办理多个packages的一种战略或手法;与其相对的是多库房(Multirepo)架构
Monorepo 目录中除了会有公共的package.json
依靠以外,在每个sub-package
子包下面,也会有其特有的package.json
依靠。
兄弟模块之间能够经过模块 package.json
界说的 name
彼此引证,确保模块之间的独立性
# monorepo目录结构
monorepo-demo
├── packages
│ ├─ module-a
│ │ ├─ src # 模块 a 的源码
│ │ ├─ node_modules # 模块 a 的 node_modules
│ │ └─ package.json # 仅模块 a 的依靠
│ └─ module-b
│ ├─ src # 模块 b 的源码
│ └─ package.json # 仅模块 b 的依靠
├── .eslintrc # 装备文件,对整个项目收效
├── node_modules # 一切子包公共的 node_modules
└── package.json # 一切子包公共的依靠
Multirepo 更倾向与在项目制中,将一个个项目运用不同的库房进行阻隔,每一个项目下运用独有的package.json
来办理依靠
# multirepo-a目录结构
multirepo-a
├── src
├── .eslintrc
├── node_modules
└── package.json
# multirepo-b目录结构
multirepo-b
├── src
├── .eslintrc
├── node_modules
└── package.json
Monorepo 东西
在选用 Monorepo(单一库房)架构的软件开发中,东西的挑选是至关重要的。适宜的 Monorepo 东西能够协助团队更高效地办理大规模代码库、进步协同开发体会以及优化构建和布置流程。
直至 2024 年,现在在前端界比较盛行的 Monorepo 东西有 Pnpm Workspaces
、Yarn Workspaces
、npm Workspaces
、Rush
、Turborepo
、Lerna
、Yalc
、和 Nx
强烈推荐运用Pnpm Workspaces
作为 Monorepo 项目的依靠办理东西😍😍😍
那么 Monorepo 与包办理东西(npm、yarn、pnpm)之间是一种怎样的联系?
这些包办理东西与 monorepo 的联系在于,它们可认为 monorepo 供给依靠装置与依靠办理的支撑,凭借本身对 workspace 的支撑,答应在 monorepo 中的不同子项目之间同享依靠项,并供给一种办理这些同享依靠项的办法,这能够简化依靠项办理和构建进程,并进步开发功率。
Monorepo 项目建立
布景
传统的多库房 Multirepo 形式,一般都是一个库房寄存一个项目。比方现在你有三个项目,就需求创立三个长途库房,而且需求为每个项目独自装置和晋级依靠
而单一库房 Monorepo 形式,就是在一个库房中办理多个项目,这些项目能够是独立的,也能够彼此依靠。经过 Monorepo,多个项目能够同享依靠。比方多个项目都需求 lodash
,那咱们也只需装置一次即可
pnpm i lodash -w
当然,Monorepo 中除了公共的package.json
依靠以外,在每个sub-package
子包下面,也会有其私有的package.json
依靠
咱们本次挑选Pnpm Workspaces
作为 Monorepo 项目的依靠办理东西,一同来建立一个 monorepo 项目✨
装置包办理东西
大局装置 pnpm
npm i pnpm -g
初始化项目
创立一个新的项目目录 pnpm-monorepo
,根目录运转 pnpm init
创立 package.json 文件
然后根目录新建一个文件夹 packages
,用于存储子包
新建 packages/libc-shared
( 同享包 ),用于寄存多个项目或组件之间同享的代码 。运转 pnpm init
创立 package.json 文件,修正 package.json 的 name 为 "@libc/shared"
;修正 package.json 的 main 进口文件途径字段为"src/index.js"
{
"name": "@libc/shared",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
}
新建 packages/libc-ui
( 公共组件包 ),即UI组件库,这儿咱们直接 clone 了 iview-ui-plus 代码。运转 pnpm install
装置依靠,
修正 package.json 的 name 为 "@libc/ui"
;修正 package.json 的 main 进口文件途径字段为"src/index.js"
然后咱们在 packages
下创立两个 vue 项目,vue-dom1
和 vue-dom2
,运转脚本pnpm create vue@latest
。因为两个项目的依靠是彻底相同的,咱们能够将 dependencies、devDependencies 复制到外层 package.json 中作为公共依靠,然后pnpm install
装置一次即可
到了这一步,vue 项目仍是不能运转,必需求先装备 workspace,用于支撑多包存储库💥让子包 vue 项目能够拜访到咱们的公共依靠💥💥
装备workspace
根目录新建一个 pnpm-workspace.yaml
,将 packages 下一切的目录都作为包进行办理💥💥💥
packages:
# all packages in direct subdirs of packages/
- 'packages/*'
pnpm-monorepo 终究项目结构
pnpm-monorepo/
├── packages/
│ ├── libc-shared/
│ ├── libc-ui/
│ ├── vue-dome1/
│ └── vue-dome2/
├── package.json
└── pnpm-workspace.yaml
子包同享💥
此刻,pnpm-workspace.yaml
作业空间下的每个子包都能够同享咱们的公共依靠了。还有个问题是,兄弟模块之间怎么同享呢?
之前咱们说过,子包之间能够经过 package.json
界说的 name
彼此引证,一同看下两个实践场景
- 怎么把子包 libc-shared 同享出去?
用--workspace
参数去装置同享子包,会去 workspace作业空间中找依靠项并装置
pnpm install @libc/shared --workspace -w
package.json
中就会主动增加如下依靠,"workspace:"
只会解析本地 workspace 包括的 package
"dependencies": {
"@libc/shared": "workspace:^"
}
此刻,vue 项目就能够运用公共包 libc-shared
里的办法,import 引进即可
import { isObject } from '@libc/shared'
- 怎么把子包 libc-ui 同享出去?
重复一下上面的过程,然后咱们去引证一个 button
组件,发现报错了 Failed to resolve import "./base" from "../libc-ui/src/components/typography/title.vue". Does the file exist?
vite.config.js 中增加 extensions
即可处理,装备一下省掉的扩展名列表
resolve: {
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
}
尽管 button
组件引证成功了,可是发现没有任何款式作用。在 libc-ui/src/index.js 文件中导入一下款式文件就行了
import "./styles/index.less";
依靠
公共依靠
大局装置公共依靠 lodash
。需求加-w
(在作业空间的根目录中发动 pnpm)
pnpm install lodash -w
这样,vue-dom1 和 vue-dom2 这两个 vue项目就都能够运用 lodash
库了
部分依靠
假如只要 vue-dom1 项目用到了 lodash
,咱们也能够装置到 vue-dom1 项目内部,不作为公共依靠项,有两种办法能够完成
- cd 到 src/packages/vue-dom1 目录下,直接装置
pnpm install lodash
- 在恣意目录下,运用
--filter
参数进行装置;package_selector:package.json 对应的 name 字段
pnpm install lodash --filter <package_selector>
shamefully-hoist
shamefully-hoist
,默许 false
-
false:
node_modules
下只能看到直接依靠的套件,次级依靠在node_modules/.pnpm
目录下;无法拜访其他子包部分装置的依靠项,例如,vue-dome2 装置的 lodash,vue-dome1 是拜访不到的 -
true:將一切套件都拉升到
node_modules
目錄下,能拜访到其他子包部分装置的依靠项,例如,vue-dome2 装置的 lodash,vue-dome1 是能拜访到的
// .npmrc
# pnpm 装备
shamefully-hoist=false
配套代码
GitHub - burc-li/pnpm-monorepo: vue3 + pnpm + monorepo 项目 demo 🍎
参阅文档
为什么 pnpm+monorepo 是组件库项目的最佳实践
打破项目瓶颈:2024 年 Monorepo 东西挑选和实践 | BEEZEN
GitHub - Tyh2001/vue3-pnpm-monorepo: 🐠 vue3 + pnpm + monorepo 项目 demo