各位靓仔靓女,大家好哇!我是你们的老朋友,今天咱们来聊聊一个听起来高大上,实则接地气的玩意儿:Vue Monorepo 项目的多团队协作。别怕,咱们不搞那些虚头巴脑的理论,直接上干货!
开场白:Monorepo,是蜜糖还是砒霜?
先问大家一个问题:你们的项目是不是也面临着组件库越来越多,团队越来越庞大,代码越来越难以维护的困境?如果是,那么 Monorepo 也许能帮你一把。
啥是 Monorepo?简单来说,就是把多个项目或者模块的代码放在同一个 Git 仓库里进行管理。听起来是不是有点像把所有鸡蛋放在一个篮子里?别慌,Monorepo 可不是让你乱来的,它有一套自己的玩法。
第一章:包管理:PNPM 的正确打开方式
在 Monorepo 里,包管理可是个重头戏。传统的 npm 或者 yarn 在这种场景下,可能会遇到依赖重复安装、构建速度慢等问题。所以,我强烈推荐使用 PNPM!
1.1 PNPM 的优势:
特性 | 描述 |
---|---|
硬链接 | 使用硬链接避免重复存储相同的依赖包,节省磁盘空间。 |
符号链接 | 创建符号链接来避免重复安装依赖包,加速安装速度。 |
扁平化依赖 | 将依赖包提升到顶层目录,避免依赖地狱。 |
更严格的依赖管理 | 默认情况下,只有在 package.json 中声明的依赖才能被导入,避免隐式依赖。 |
1.2 PNPM 在 Monorepo 中的应用:
首先,在项目根目录下安装 PNPM:
npm install -g pnpm
然后,创建一个 pnpm-workspace.yaml
文件,告诉 PNPM 哪些目录是工作区:
packages:
- 'packages/*' # 所有在 packages 目录下的文件夹
- 'apps/*' # 所有在 apps 目录下的文件夹
这个文件告诉 PNPM,packages
和 apps
目录下的所有文件夹都是独立的项目,需要进行包管理。
接下来,在每个项目目录下(例如 packages/ui-components
)创建一个 package.json
文件,定义项目的依赖和脚本:
// packages/ui-components/package.json
{
"name": "@your-org/ui-components",
"version": "0.1.0",
"description": "A collection of UI components",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "vue-tsc --noEmit && vite build",
"dev": "vite",
"lint": "eslint . --ext .vue,.js,.jsx,.ts,.tsx",
"format": "prettier --write ."
},
"dependencies": {
"vue": "^3.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.0.0",
"typescript": "^4.0.0",
"vite": "^4.0.0",
"vue-tsc": "^1.0.0"
}
}
现在,你可以在项目根目录下运行 pnpm install
,PNPM 会自动安装所有工作区的依赖,并进行优化。
1.3 项目之间的依赖:
如果一个项目需要依赖另一个项目,可以直接在 package.json
中声明:
// apps/my-app/package.json
{
"name": "@your-org/my-app",
"version": "0.1.0",
"dependencies": {
"@your-org/ui-components": "workspace:*" // 依赖本地的 ui-components 项目
}
}
workspace:*
告诉 PNPM,这个依赖指向本地的 ui-components
项目。这样,当你修改 ui-components
的代码时,my-app
会自动使用最新的代码,而不需要重新发布和安装。
第二章:版本控制:Git 的高级玩法
在 Monorepo 中,版本控制也需要一些技巧。传统的 Git 工作流可能无法满足多团队协作的需求。
2.1 Git 分支策略:
我推荐使用 Gitflow 或者 GitHub Flow。Gitflow 比较复杂,适合大型项目;GitHub Flow 比较简单,适合中小型项目。
- Gitflow: 主要分支有
main
(长期存在的发布分支)、develop
(集成所有新功能的分支)和 feature 分支、release 分支、hotfix 分支。 - GitHub Flow: 主要分支是
main
,所有新功能都在 feature 分支上开发,然后合并到main
。
2.2 代码审查:
代码审查是保证代码质量的重要环节。可以使用 GitHub 的 Pull Request 功能进行代码审查。
2.3 提交规范:
为了方便自动化构建和发布,我们需要遵循一定的提交规范。我推荐使用 Angular 的提交规范:
<type>(<scope>): <subject>
<body>
<footer>
- type: 提交的类型,例如
feat
(新功能)、fix
(bug 修复)、docs
(文档)、style
(代码风格)、refactor
(重构)、test
(测试)、chore
(构建过程或辅助工具的变动)。 - scope: 影响的范围,例如
ui-components
、my-app
。 - subject: 提交的简短描述。
- body: 提交的详细描述。
- footer: 关闭的 issue 或者相关的链接。
例如:
feat(ui-components): add a new button component
This commit adds a new button component to the ui-components library.
Closes #123
可以使用 commitlint
工具来强制执行提交规范:
npm install --save-dev @commitlint/config-conventional @commitlint/cli husky
然后,创建一个 commitlint.config.js
文件:
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
};
最后,在 package.json
中添加 husky hook:
{
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
}
2.4 版本管理:
Monorepo 的版本管理比较复杂,因为每次提交都可能影响多个项目。我推荐使用 lerna
或者 changesets
来进行版本管理。
- Lerna: 自动检测哪些项目发生了变化,并自动更新版本号和发布到 npm。
- Changesets: 手动创建 changeset 文件来描述每个提交对项目的影响,然后自动更新版本号和发布到 npm。
这里我们选择 changesets
,因为它更灵活,更适合多团队协作。
首先,安装 changesets
:
npm install --save-dev @changesets/cli
然后,初始化 changesets
:
pnpm changeset init
这会在项目根目录下创建一个 .changeset
文件夹。
每次提交之前,运行 pnpm changeset
命令,创建一个 changeset 文件,描述本次提交对项目的影响:
pnpm changeset
这个命令会引导你选择受影响的项目,并填写 changeset 的描述。
例如:
---
"@your-org/ui-components": patch
---
Add a new button component.
这个文件表示本次提交对 ui-components
项目进行了 patch 版本的更新。
在发布之前,运行 pnpm changeset version
命令,根据 changeset 文件自动更新版本号:
pnpm changeset version
最后,运行 pnpm changeset publish
命令,发布到 npm:
pnpm changeset publish
第三章:构建流程:自动化是王道
在 Monorepo 中,构建流程也需要自动化。可以使用 CI/CD 工具(例如 GitHub Actions、GitLab CI、Jenkins)来自动化构建、测试和发布流程。
3.1 构建脚本:
在每个项目的 package.json
文件中,定义构建脚本:
// packages/ui-components/package.json
{
"scripts": {
"build": "vue-tsc --noEmit && vite build"
}
}
3.2 CI/CD 配置:
以 GitHub Actions 为例,创建一个 .github/workflows/ci.yml
文件:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install -g pnpm
- run: pnpm install
- run: pnpm run build
- run: pnpm run test
这个文件定义了一个 CI 流程,当有代码推送到 main
分支或者有 Pull Request 时,会自动运行构建和测试脚本。
3.3 发布流程:
在 CI/CD 流程中,可以添加发布步骤,自动发布到 npm:
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install -g pnpm
- run: pnpm install
- run: pnpm run build
- run: pnpm run test
- run: npx changeset version
- run: git config --global user.name "GitHub Actions"
- run: git config --global user.email "[email protected]"
- run: npx changeset publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
这个文件定义了一个发布流程,当有代码推送到 main
分支时,会自动运行构建、测试、更新版本号和发布到 npm。
第四章:团队协作:沟通是桥梁
在 Monorepo 中,团队协作非常重要。需要建立良好的沟通机制,避免代码冲突和重复工作。
4.1 代码规范:
统一的代码规范可以减少代码风格的差异,提高代码的可读性和可维护性。可以使用 ESLint 和 Prettier 来强制执行代码规范。
4.2 代码审查:
代码审查是保证代码质量的重要环节。可以使用 GitHub 的 Pull Request 功能进行代码审查。
4.3 文档:
完善的文档可以帮助团队成员了解项目的结构、功能和使用方法。可以使用 Storybook 来编写组件文档。
4.4 沟通工具:
可以使用 Slack、钉钉等沟通工具来及时沟通和解决问题。
第五章:Monorepo 的坑:避坑指南
Monorepo 虽然有很多优点,但也存在一些坑。
5.1 构建时间:
Monorepo 的构建时间可能会比较长,可以使用缓存来加速构建。
5.2 代码冲突:
Monorepo 的代码冲突可能会比较频繁,需要加强代码审查和沟通。
5.3 权限管理:
Monorepo 的权限管理比较复杂,需要仔细规划。
总结:Monorepo,值得一试!
Monorepo 是一种强大的代码管理方式,可以提高代码的复用性、可维护性和协作效率。但是,Monorepo 也存在一些挑战,需要仔细规划和管理。
希望今天的讲座能帮助大家更好地理解和应用 Monorepo。如果大家有什么问题,欢迎随时提问!下次再见!