重要信息:此文档涵盖 Yarn 1(经典)。
有关 Yarn 2+ 文档和迁移指南,请访问 yarnpkg.com。

工作区

工作区是设置软件包架构的新方式,从 Yarn 1.0 开始默认可用。它允许你以这种方式设置多个软件包,只需运行一次 yarn install 即可一次性安装所有这些软件包。

你为什么要这样做?

  • 你的依赖项可以链接在一起,这意味着你的工作区可以相互依赖,同时始终使用最新的可用代码。这也是比 yarn link 更好的机制,因为它只影响你的工作区树,而不是你的整个系统。

  • 你的所有项目依赖项将一起安装,使 Yarn 有更大的自由度来更好地优化它们。

  • Yarn 将使用一个锁文件,而不是为每个项目使用不同的锁文件,这意味着更少的冲突和更轻松的审查。

如何使用?

package.json 文件中添加以下内容。从现在开始,我们将这个目录称为“工作区根”

package.json

{
  "private": true,
  "workspaces": ["workspace-a", "workspace-b"]
}

请注意需要 private: true!工作区不打算发布,所以我们添加了这个安全措施以确保没有任何东西可以意外地公开它们。

创建此文件后,创建两个名为 workspace-aworkspace-b 的新子文件夹。在每个文件夹中,使用以下内容再创建一个 package.json 文件

workspace-a/package.json

{
  "name": "workspace-a",
  "version": "1.0.0",

  "dependencies": {
    "cross-env": "5.0.5"
  }
}

workspace-b/package.json

{
  "name": "workspace-b",
  "version": "1.0.0",

  "dependencies": {
    "cross-env": "5.0.5",
    "workspace-a": "1.0.0"
  }
}

最后,在某个地方运行 yarn install,最好在工作区根目录中运行。如果一切工作正常,你现在应该有一个类似的文件层次结构

/package.json
/yarn.lock

/node_modules
/node_modules/cross-env
/node_modules/workspace-a -> /workspace-a

/workspace-a/package.json
/workspace-b/package.json

注意:不要寻找 /node_modules/workspace-b。除非其他软件包将其用作依赖项,否则它将不存在。

就这样!现在从位于 workspace-b 中的文件中调用 workspace-a 将使用当前位于你的项目中的确切代码,而不是 npm 上发布的代码,并且 cross-env 软件包已被正确地进行重复数据删除并放在你的项目根目录中,以便 workspace-aworkspace-b 使用。

请注意,/workspace-a 已通过符号链接别名为 /node_modules/workspace-a。此技巧可以让你像引用普通包一样引用此包!你还要知道,/workspace-a/package.json#name 字段是可用的,而不是文件夹名称。这意味着,如果 /workspace-a/package.json 字段 name"pkg-a",别名将会如下:/node_modules/pkg-a -> /workspace-a,你将能够通过使用 const pkgA = require("pkg-a");(或者 import pkgA from "pkg-a";),从 /workspace-a 导入代码。

它与 Lerna 相比如何?

Yarn 的工作区是诸如 Lerna 之类的工具可以(而且 可以!)使用的底层基础项。它们绝不会尝试支持 Lerna 提供的高级功能,但是,通过在 Yarn 内部实现分辨率和链接步骤的核心逻辑,我们希望启用新的用法并提高性能。

技巧和窍门

  • workspaces 字段是一个包含每个工作区路径的数组。由于跟踪每个工作区可能很繁琐,因此此字段还接受全局模式!例如,Babel 会通过单一 packages/* 指令引用其所有包。

  • 工作区足够稳定,可用于大规模应用程序,并且不应更改常规安装工作方式的任何内容,但如果你认为它们破坏了某些内容,你可以通过向 Yarnrc 文件添加以下行来禁用它们

    workspaces-experimental false
    
  • 如果你只对一个工作区进行更改,请使用 –focus 从注册表快速安装兄弟节点,而不是从头构建所有兄弟节点。

限制和注意事项

  • 你的工作区和用户将获得的内容(工作区依赖项将提升到文件系统层次结构的更高位置)之间的包布局将不同。由于提升过程尚未标准化,因此对该布局的假设本来就存在风险,从理论上来讲,这里没有新内容。如果你遇到问题,请尝试使用 nohoist 选项

  • 在上面的示例中,如果 workspace-b 依赖的版本不同于 workspace-a 的 package.json 中引用的版本,那么该依赖项将从 npm 安装,而不是从本地文件系统链接。这是因为一些包实际上需要使用以前版本才能构建新版本(Babel 是其中之一)。

  • 在工作区中发布包时要小心。如果你正在准备下一次发布并决定使用新依赖项但忘记在 package.json 文件中声明它,则如果另一个包已将该依赖项下载到工作区根目录,你的测试在本地仍可能通过。然而,对于从注册表中提取该依赖项的使用者来说,它将会中断,因为现在依赖项列表不完整,所以他们无法下载新依赖项。目前,无法在此场景中发出警告。

  • 在文件夹层次结构方面,工作区必须是工作区根的后代。你不能也不能引用位于此文件系统层次结构之外的工作区。

  • 目前不支持嵌套工作区。