在一个多团队协作的 Vue Monorepo 项目中,你会如何进行包管理、版本控制和构建流程设计?

各位靓仔靓女,大家好哇!我是你们的老朋友,今天咱们来聊聊一个听起来高大上,实则接地气的玩意儿: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,packagesapps 目录下的所有文件夹都是独立的项目,需要进行包管理。

接下来,在每个项目目录下(例如 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-componentsmy-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。如果大家有什么问题,欢迎随时提问!下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注