各位靓仔靓女,准备好起飞了吗?Vue Monorepo 最佳实践讲座,现在开始!
大家好!今天咱们不聊情怀,只谈干货。现在都流行 Monorepo,尤其是 Vue 项目越做越大,拆成 Monorepo 管理几乎成了标配。但是,随之而来的就是依赖管理、构建、部署等等一系列问题。别慌!今天我就教你们如何用 pnpm
或者 Turborepo
这种神器,把这些问题安排得明明白白!
啥是 Monorepo?先简单唠两句
简单来说,Monorepo 就是把多个项目/包/组件库放在同一个代码仓库里管理。
- 优点: 代码复用性高、依赖版本统一、方便统一管理和发布。
- 缺点: 构建速度慢、代码可见性问题(需要控制权限)、仓库体积大。
为什么选 pnpm
或 Turborepo
?
pnpm
和 Turborepo
都是为了解决 Monorepo 带来的问题的利器,它们各有千秋:
pnpm
: 强调高效磁盘空间利用和速度,通过硬链接和符号链接共享依赖,避免重复安装。Turborepo
: 强调增量构建和任务编排,只构建发生改变的部分,极大地提升构建速度。
咱们可以把它们想象成:
pnpm
:一个精打细算的仓库管理员,能把仓库里的东西安排得井井有条,省空间又省力。Turborepo
:一个高效的生产线调度员,能根据生产需求,合理安排生产任务,最大限度地提高生产效率。
实战:用 pnpm
管理 Vue Monorepo
1. 初始化 Monorepo 项目
首先,创建一个空的目录,然后初始化 pnpm
:
mkdir vue-monorepo
cd vue-monorepo
pnpm init
这会在你的项目根目录下生成一个 package.json
文件。
2. 创建 Packages
在根目录下创建一个 packages
目录,用来存放各个子项目。
mkdir packages
然后,在 packages
目录下创建两个 Vue 项目:web
和 components
。
cd packages
vue create web # 创建一个 Vue 应用
vue create components # 创建一个 Vue 组件库
这里需要你已经安装了 Vue CLI。
3. 配置 pnpm-workspace.yaml
在项目根目录下创建一个 pnpm-workspace.yaml
文件,告诉 pnpm
如何管理你的 Monorepo。
packages:
- 'packages/*' # 所有在 packages 目录下的包
- '!packages/web/node_modules/**' # 排除 web 项目的 node_modules
- '!packages/components/node_modules/**' # 排除 components 项目的 node_modules
4. 安装依赖
回到项目根目录,运行 pnpm install
。 pnpm
会自动分析 pnpm-workspace.yaml
文件,并安装所有子项目的依赖。
pnpm install
pnpm
的一大亮点就是 hoisting。它会将所有公共依赖提升到根目录的 node_modules
中,减少冗余。
5. 子项目依赖共享
假设 web
项目需要使用 components
组件库,只需要在 web
项目的 package.json
中添加依赖:
// packages/web/package.json
{
"name": "web",
"version": "0.1.0",
"dependencies": {
"components": "workspace:*" // "workspace:*" 表示使用 workspace 中的 components
}
}
然后,在项目根目录下再次运行 pnpm install
。pnpm
会自动将 components
组件库链接到 web
项目的 node_modules
中。
6. 定义 Scripts
在根目录的 package.json
中定义一些常用的 scripts,方便统一管理各个子项目:
// package.json
{
"name": "vue-monorepo",
"version": "1.0.0",
"scripts": {
"build:web": "pnpm --filter web build",
"dev:web": "pnpm --filter web dev",
"build:components": "pnpm --filter components build",
"lint": "pnpm --filter web lint",
"test": "pnpm --filter web test"
}
}
pnpm --filter <package_name> <command>
可以指定在某个子项目中执行命令。
7. 发布组件库
如果想将 components
组件库发布到 npm 上,可以按照以下步骤:
- 在
components
项目的package.json
中设置name
、version
、description
等信息。 - 登录 npm:
npm login
- 运行
pnpm publish --filter components
。
实战:用 Turborepo
加速构建
1. 初始化 Turborepo
在项目根目录下运行以下命令,初始化 Turborepo:
npm install -g turbo
turbo init
这会创建一个 turbo.json
文件,用来配置 Turborepo。
2. 配置 turbo.json
turbo.json
是 Turborepo 的核心配置文件。
// turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"], // 依赖关系:如果依赖的包 build 了,当前包才会 build
"outputs": [".output/**", "dist/**"] // 输出目录
},
"lint": {},
"dev": {
"cache": false, // 开发环境不缓存
"persistent": true // 持久化进程,保持热更新
}
}
}
pipeline
:定义各个任务的依赖关系和输出目录。dependsOn
:定义任务的依赖关系。^build
表示依赖当前包的所有依赖包的build
任务。outputs
:定义任务的输出目录。Turborepo 会根据输出目录来判断任务是否需要重新执行。cache
:是否缓存任务的结果。persistent
: 是否保持进程运行。
3. 修改 Scripts
修改根目录的 package.json
文件,使用 turbo
命令来执行任务:
// package.json
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test"
}
}
4. 构建
运行 pnpm build
或者 npm run build
,Turborepo 会自动分析各个子项目的依赖关系,并并行构建。
第一次构建会比较慢,但是后续的构建会非常快,因为 Turborepo 会缓存构建结果。
5. 增量构建
如果只修改了 components
组件库,再次运行 pnpm build
,Turborepo 只会构建 components
项目,而不会重新构建 web
项目。这就是增量构建的威力!
pnpm
vs Turborepo
:怎么选?
特性 | pnpm |
Turborepo |
---|---|---|
核心功能 | 依赖管理、节省磁盘空间、速度更快 | 增量构建、任务编排、缓存 |
适用场景 | 所有 Monorepo 项目 | 大型、复杂的 Monorepo 项目,对构建速度要求高 |
学习曲线 | 简单 | 稍复杂 |
与 CI/CD | 兼容性好 | 专门为 CI/CD 优化 |
总结:
- 如果你的 Monorepo 项目规模不大,对构建速度没有特别高的要求,那么
pnpm
就足够了。 - 如果你的 Monorepo 项目非常庞大,构建速度慢到让你怀疑人生,那么
Turborepo
绝对值得尝试。 - 当然,你也可以将
pnpm
和Turborepo
结合使用,充分发挥它们的优势。pnpm
管理依赖,Turborepo
加速构建,简直是 Monorepo 的黄金搭档!
进阶技巧
- 使用
.npmrc
文件配置 npm 源、代理等信息。 - 使用
changesets
管理版本发布。 - 使用 CI/CD 工具(如 GitHub Actions、Jenkins)自动化构建、测试和部署流程。
- 合理划分子项目,避免过度耦合。
- 定期清理无用依赖,保持仓库整洁。
常见问题
- Q: 为什么我的构建速度还是很慢?
- A: 检查你的
turbo.json
配置是否正确,确保依赖关系和输出目录设置正确。 - A: 检查你的代码是否存在循环依赖。
- A: 检查你的 CI/CD 环境是否配置了缓存。
- A: 检查你的
- Q: 如何解决依赖冲突?
- A: 尽量保持依赖版本统一。
- A: 使用
pnpm dedupe
命令清理重复依赖。 - A: 使用
resolutions
字段强制指定依赖版本。
- Q: 如何控制代码可见性?
- A: 可以使用
private
字段将子项目标记为私有,防止被意外发布到 npm 上。 - A: 可以使用访问控制列表 (ACL) 限制对子项目的访问权限。
- A: 可以使用
总结
今天我们一起学习了如何使用 pnpm
和 Turborepo
管理 Vue Monorepo 项目。希望这些知识能帮助你在 Monorepo 的道路上越走越远。记住,没有银弹,只有不断学习和实践,才能找到最适合你的解决方案。
好了,今天的讲座就到这里。感谢大家的聆听!希望大家都能成为 Monorepo 大师,早日实现代码自由!
最后,祝大家 Bug 少一点,头发多一点!