构建您的仓库

管理依赖

学习如何在 Turborepo 工作区中有效管理外部和内部依赖项的最佳实践
  • 外部依赖 来自 npm 注册表,允许您利用生态系统中的宝贵代码来更快地构建应用程序和库。
  • 内部依赖 让您在仓库内共享功能,显著提高共享代码的可发现性和可用性。我们将在下一个指南中讨论如何构建内部包。
// ./apps/web/package.json
{
  "dependencies": {
    "next": "latest", // 外部依赖
    "@repo/ui": "workspace:*" // 内部依赖
  }
}

依赖安装的最佳实践

在使用依赖的地方安装依赖

当您在仓库中安装依赖时,应该直接在使用它的包中安装。包的 package.json 将包含该包需要的每个依赖项。这对外部依赖和内部依赖都适用。

请注意,您的包管理器可能会选择使用与包不同的 node_modules 位置

要快速在多个包中安装依赖,您可以使用包管理器:

pnpm add jest --save-dev --recursive --filter=web --filter=@repo/ui --filter=docs

这种做法有几个好处:

  • 提高清晰度:当依赖项列在包的 package.json 中时,更容易理解包依赖什么。在仓库中工作的开发人员可以一目了然地看到包中使用了哪些依赖项。
  • 增强灵活性:在大规模的 monorepo 中,期望每个包使用相同版本的外部依赖可能是不现实的。当许多团队在同一个代码库中工作时,由于大规模运营的现实,会有不同的优先级、时间表和需求。通过在使用依赖的包中安装依赖,您可以让 ui 团队升级到最新版本的 TypeScript,而 web 团队可以优先发布新功能,稍后再升级 TypeScript。此外,如果您仍然希望保持依赖版本同步,您也可以做到这一点
  • 更好的缓存能力:如果您在仓库根目录安装太多依赖项,每当您添加、更新或删除依赖项时,您都会更改工作区根目录,导致不必要的缓存未命中。
  • 修剪未使用的依赖项:对于 Docker 用户,Turborepo 的修剪功能可以从 Docker 镜像中删除未使用的依赖项,以创建更轻的镜像。当依赖项安装在它们所属的包中时,Turborepo 可以读取您的锁文件并删除您需要的包中未使用的依赖项。

根目录中的依赖项要少

遵循上述第一个原则在使用依赖的包中安装依赖项,您会发现您自然会在工作区根目录中拥有很少的依赖项。

唯一属于工作区根目录的依赖项是用于管理仓库的工具,而用于构建应用程序和库的依赖项则安装在各自的包中。一些适合安装在根目录的依赖项示例包括 turbohuskylint-staged

管理依赖项

Turborepo 不管理依赖项

请注意,Turborepo 不参与管理您的依赖项,将这项工作留给您选择的包管理器。

包管理器负责处理诸如下载正确的外部依赖版本、符号链接和解析模块等事情。本页面的建议是在工作区中管理依赖项的最佳实践,并不由 Turborepo 强制执行。

包管理器之间的模块解析不同

包管理器有不同的模块解析算法,这导致行为差异,可能难以预测。

在 Turborepo 文档中,我们根据包管理器的预期行为提出了许多建议。我们对如何处理依赖项的覆盖是尽力而为的,您可能需要根据您的包管理器或仓库的需求调整文档化的行为。

但是,如果您发现文档中的问题对于所有包管理器或特定包管理器来说似乎普遍不正确,请通过 GitHub Issue 告诉我们,以便我们改进。

node_modules 位置

根据您选择的包管理器、版本、设置以及依赖项在工作区中的安装位置,您可能会在工作区内的各个位置看到 node_modules 及其内部的依赖项。依赖项可能在根目录 node_modules、包的 node_modules 或两者中找到。

只要您的脚本和任务能够找到它们需要的依赖项,您的包管理器就工作正常。

工作区内 node_modules 的特定位置不是包管理器公共 API 的一部分。这意味着直接引用 node_modules(如 node ./node_modules/a-package/dist/index.js)可能是脆弱的,因为依赖项在磁盘上的位置可能会随着工作区周围的其他依赖项更改而改变。

相反,尽可能依赖 Node.js 生态系统的约定来访问依赖模块。

保持依赖版本一致

一些 monorepo 维护者更喜欢按规则在所有包中保持依赖项的相同版本。有几种方法可以实现这一点:

使用专用工具

syncpackmanypkgsherif 这样的工具可以用于这个特定目的。

使用包管理器

您可以使用包管理器在一个命令中更新依赖版本。

pnpm up --recursive typescript@latest

pnpm catalogs

在 pnpm v9.5+ 中,您可以使用 catalogs 将依赖版本范围定义为可重用常量。这将保持依赖项在相同版本上,因为您在整个工作区中引用相同的值。

要了解更多信息,访问 pnpm catalogs 文档

使用 IDE

您的 IDE 的重构工具可以一次性在仓库中的所有 package.json 文件中查找和替换依赖项的版本。尝试在 package.json 文件上使用像 "next": ".*" 这样的正则表达式来查找 next 包的所有实例,并将它们替换为您想要的版本。完成后,确保运行包管理器的安装命令来更新您的锁文件。

下一步

现在您知道如何在工作区中有效管理依赖项,让我们创建一个内部包作为 monorepo 中的依赖项使用。