在一个大型 Vue Monorepo 项目中,如何利用 `pnpm` 或 `Turborepo` 等工具,管理依赖、构建和部署流程?

各位靓仔靓女,准备好起飞了吗?Vue Monorepo 最佳实践讲座,现在开始!

大家好!今天咱们不聊情怀,只谈干货。现在都流行 Monorepo,尤其是 Vue 项目越做越大,拆成 Monorepo 管理几乎成了标配。但是,随之而来的就是依赖管理、构建、部署等等一系列问题。别慌!今天我就教你们如何用 pnpm 或者 Turborepo 这种神器,把这些问题安排得明明白白!

啥是 Monorepo?先简单唠两句

简单来说,Monorepo 就是把多个项目/包/组件库放在同一个代码仓库里管理。

  • 优点: 代码复用性高、依赖版本统一、方便统一管理和发布。
  • 缺点: 构建速度慢、代码可见性问题(需要控制权限)、仓库体积大。

为什么选 pnpmTurborepo

pnpmTurborepo 都是为了解决 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 项目:webcomponents

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 installpnpm 会自动分析 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 installpnpm 会自动将 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 上,可以按照以下步骤:

  1. components 项目的 package.json 中设置 nameversiondescription 等信息。
  2. 登录 npm:npm login
  3. 运行 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 绝对值得尝试。
  • 当然,你也可以将 pnpmTurborepo 结合使用,充分发挥它们的优势。pnpm 管理依赖,Turborepo 加速构建,简直是 Monorepo 的黄金搭档!

进阶技巧

  • 使用 .npmrc 文件配置 npm 源、代理等信息。
  • 使用 changesets 管理版本发布。
  • 使用 CI/CD 工具(如 GitHub Actions、Jenkins)自动化构建、测试和部署流程。
  • 合理划分子项目,避免过度耦合。
  • 定期清理无用依赖,保持仓库整洁。

常见问题

  • Q: 为什么我的构建速度还是很慢?
    • A: 检查你的 turbo.json 配置是否正确,确保依赖关系和输出目录设置正确。
    • A: 检查你的代码是否存在循环依赖。
    • A: 检查你的 CI/CD 环境是否配置了缓存。
  • Q: 如何解决依赖冲突?
    • A: 尽量保持依赖版本统一。
    • A: 使用 pnpm dedupe 命令清理重复依赖。
    • A: 使用 resolutions 字段强制指定依赖版本。
  • Q: 如何控制代码可见性?
    • A: 可以使用 private 字段将子项目标记为私有,防止被意外发布到 npm 上。
    • A: 可以使用访问控制列表 (ACL) 限制对子项目的访问权限。

总结

今天我们一起学习了如何使用 pnpmTurborepo 管理 Vue Monorepo 项目。希望这些知识能帮助你在 Monorepo 的道路上越走越远。记住,没有银弹,只有不断学习和实践,才能找到最适合你的解决方案。

好了,今天的讲座就到这里。感谢大家的聆听!希望大家都能成为 Monorepo 大师,早日实现代码自由!

最后,祝大家 Bug 少一点,头发多一点!

发表回复

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