在 Ubuntu 中安装 Yarn

2025年3月17日 | 阅读 15 分钟

Yarn是一个软件打包系统,于2016年为运行时环境,即Facebook的Node.js JavaScript而集成。作为npm包管理器的替代品,Yarn是Tiled(Ember.js背后的公司)、Google、Exponent(现Expo.dev)和Facebook合作开发的,旨在解决大型代码库在性能、安全性和一致性方面的问题。

Yarn允许我们与世界各地的其他开发者共享和使用代码。它以可靠、安全和快速的方式完成这项工作,让我们无需担心。Yarn允许我们利用其他开发者解决不同问题的方案,方便我们集成软件。如果我们遇到问题,可以在GitHub上报告问题或贡献代码,并在问题修复后使用Yarn来保持一切的更新。

代码通过一种称为package的东西进行共享。一个package包含所有分发代码以及一个package.json文件(称为manifest),该文件定义了package。Yarn是一个新的包管理器,它取代了以前的npm客户端或许多其他包管理器的工作流程,同时与其他与npm registry兼容。它包含了与以前的工作流程相同的方面,同时实现了更快、更多、更可靠和更安全。

Yarn的通用架构

Yarn从一个核心包(发布为@yarnpkg/core)开始,该包公开了构成项目的多个基本元素。其中一些元素是我们可能从API中识别出的类:Manifest, Cache, Workspace, Project, Configuration等。这些都由核心包提供。

核心本身并不做太多事情,它包含了管理项目所需的逻辑。为了通过命令行应用此逻辑,Yarn提供了一个称为@yarnpkg/cli的间接层,它本身也做不了太多。但是,它有两个非常重要的职责:它将Yarn的预构建插件注入到一个环境中,并根据当前目录(cwd)来实例化一个项目。

Yarn是一种内置的现代化方式,允许将大部分与第三方交互相关的企业逻辑实现在其包中。例如,npm解析器是众多插件之一。这种架构为我们提供了一个更容易处理的代码库(从而提高了稳定性和开发速度),并使插件作者能够编写外部逻辑,而无需修改Yarn本身的代码库。

Yarn的功能

用户可以指定Yarn的插件

Install Yarn Ubuntu

离线缓存

下载的包被存储并缓存为单个文件。

约束

Yarn的约束允许用户强制执行有关其依赖项或作用域工作区周围的多个字段的规则。

插件

它可以添加新的命令、链接器、功能和解析器,并可以注册到某些事件或相互开发。Yarn的绝大多数功能都通过插件实现,包括yarn install和yarn add,它们本身也是预装插件。

即插即用 (Plug'n'Play)

它允许用户在不使用文件夹的情况下执行Node项目,即node_modules,通过Plug'n'Play控制文件定义解析依赖包文件的位置或方式。这个特性旨在解决node_modules结构混乱的问题,并带来更快的Node.js软件启动时间。

发布工作流

当根包被升级时,它会自动升级多个工作区中对应的包。

协议

用户可以指定使用哪种协议来解析某些包。例如,git协议用于通过Git仓库下载公共包,而patch协议用于创建实际包的修补副本。

零安装 (Zero-installs)

零安装解决了当代码刚刚获取到本地时对包安装的需求。

工作区 (Workspaces)

工作区允许一个仓库中的多个项目协同工作,并在源代码更改时自动使用其他关联方的修改,只需执行一次yarn install即可安装所有这些包,每项都在一个独立的传递中完成。

Yarn术语

  • 构建脚本 (Build Script): 指包安装完成后立即运行的操作。post-install脚本通常在脚本字段的manifest中配置。它们应该留给原生依赖项。实际上,真实JavaScript包没有理由使用它们。构建脚本对用户的项目有严重的副作用,因此请仔细权衡是否真的需要它们。
  • 依赖项 (Dependency): 依赖项(在manifest的dependencies字段中列出)指定了两个不同包之间的连接。如果安装过程成功,并且A包含依赖项B,Yarn将确保包A可以访问包B。

注意:这是我们对常规依赖项做出的唯一保证。然而,不能保证包B将与在应用程序其他部分使用的包是同一版本。

  • 描述符 (Descriptor): 是包名和包范围的组合。描述符用于识别一组包,而不是一个特定的包。
  • 开发依赖项 (Development Dependency): 依赖项(在manifest的devDependencies字段中列出)指定了两个不同包之间的连接。开发依赖项与常规依赖项非常相似,只是它们仅对本地包重要。从npm等远程注册表检索的包无法访问开发依赖项;然而,使用本地源(如portal:协议或工作区)安装的包可以。
  • 获取器 (Fetcher): 获取器负责从任何引用中提取完整的包数据。例如,npm获取器将从npm注册表下载包的tarball。
  • 提升 (Hoisting): 提升是转换依赖树以通过删除尽可能多的节点来改进它的过程。没有一种方法可以确定如何转换树,并且不同的包管理器会做出不同的权衡。因此,不能保证最终的提升布局,除了包始终可以访问其在manifest中命名的依赖项。

由于提升与Node解析和文件系统密切相关,其设计使得在不正确指定为依赖项的情况下仍然可以轻松地创建bug并意外访问包。因此,在其提升过程中,它们的出现是不可预测的,并且无法被观察到。

  • 链接器 (Linker): 链接器是一些组件,它们使用包数据存储和依赖树,并返回特定于其目标平台的磁盘伪影。例如,Plug'n'Play链接器生成一个.pnp.cjs文件。
  • 定位器 (Locator): 是包引用和包名的集合。定位器用于识别一个唯一的包。
  • 单仓库 (Monorepository): 是一个包含两个或多个包的仓库。例如,Jest和Babel就是这样的仓库示例。它们都包含许多相互依赖的小包。
  • 清单 (Manifest): 是package.json文件。
  • 包 (Packages): 它们是依赖树节点。一个包是一组源代码,通常由根目录下的package.json定义。包可以指定依赖项,即为了使其正常工作需要存在的其他包。
  • 对等依赖项 (Peer dependency): 依赖项(在manifest的peerDependencies字段中列出)指定了两个不同包之间的连接。
  • 对等依赖包 (Peer-dependent Package): 是一个声明了对等依赖项的包。
  • 插件 (Plugin): 是Yarn 2+中引入的一个新概念。Yarn可以通过添加新的链接器、获取器或解析器来扩展和增强功能。
  • 即插即用 (Plug'n'Play): 是一种替代的安装计划,它生成一个文件,然后将其插入到node中,让其了解在哪里搜索已安装的包,而不是生成传统的node_modules目录。从2.0版本开始,Plug'n'Play成为JavaScript项目的默认安装计划。
  • 门户 (Portal): 是一个使用portal:协议的依赖项,表示一个位于磁盘上的包。

与link:协议相反,Yarn将配置其依赖项映射,使得不仅依赖项可以访问通过门户引用的文件,而且门户本身也可以访问其依赖项。

  • 项目 (Project): 这个术语用于包含与同一个依赖树相关的所有工作区。
  • 范围 (Range): 是一个字符串,当与包名合并时,可用于选择一个包的两个或多个版本。通常,范围遵循semver,但也可以使用Yarn支持的协议。
  • 引用 (Reference): 是一个字符串,当与包名合并时,可用于选择一个包的一个版本。通常,引用遵循semver,但也可以使用Yarn支持的协议。
  • 解析器 (Resolver): 解析器负责将描述符转换为定位器,并使用包定位器选择包清单。例如,npm解析器会检查npm注册表上存在哪些版本,并提供所有符合semver要求的候选包。然后,它会检查npm注册表以获取所选解析的完整元数据。
  • 范围 (Scope): 是一个通过npm注册表继承的术语,用于定义属于同一实体的包的组。例如,所有Yarn包在npm注册表上都属于berry范围的2.0版本。传统上,范围以@符号作为前缀。
  • 单例包 (Singleton Package): 是在依赖树周围实例化一次的包。单例包可以通过对等依赖项轻松创建,通过使用其属性之一,而它们本身不是一等公民。因为对等依赖项所依赖的包保证是与其祖先使用的包相同的实例,所以跨越对等依赖项到最近工作区的所有依赖分支都将确保只创建一个包的实例,使其成为现有包。
  • 传递性依赖 (Transitive Dependency): 是我们依赖的包的依赖项。如果谈论react,我们的应用程序依赖于它,那么它就是直接依赖项。然而,react也依赖于prop-types,这使得它们成为传递性依赖项。
  • 未解压包 (Unplugged Package): 使用Yarn PnP,几乎所有包都保存在其zip存档中,而不是解压到磁盘上。然后在运行时,存档被挂载到文件系统上并透明地访问。挂载是只读的,因此当有东西试图写入它们时,存档不会损坏。

然而,在某些情况下,保持包只读可能很困难。对于这些情况,Yarn无法解压相应的包,而是将它们保留在各自的文件夹中。这类包被称为“未解压”。在某些情况下,包会被解压

  • 如果包隐式包含原生文件
  • 如果包隐式声明了post-install脚本
  • 如果包显式设置了preferUnplugged字段为true
  • 通过显式将unplugged字段设置为true
  • 虚拟包 (Virtual Package): 对等依赖包可能具有两个或多个依赖集,因为这些包实际上指定了一个潜在依赖集的范围,而不是一个静态的依赖集。当发生这种情况时,包至少需要为所有这些集合实例化一次。
    • 由于JS模块和Node环境是根据它们的路径实例化的,并且PnP使其在任何给定项目中包只实例化一次;表示这些包的一种方法是为它们提供多个路径。
    • 虚拟包在这些情况下非常有用。
    • 虚拟包是对等依赖包的特殊实例,它编码了该特定实例应使用的依赖项集。
    • 所有虚拟包都提供了一个特殊的文件系统路径,以确保其指向的脚本将使用正确的依赖集进行实例化。

以前,虚拟包是通过符号链接管理的,但最近已经改变,它们现在通过虚拟文件系统层进行管理。这避免了创建许多令人困惑的符号链接的需要,提高了Windows兼容性,并防止了第三方工具(称为realpath)可能带来的问题。

  • 工作区 (Workspace): 一般来说,工作区是Yarn的一个方面,用于处理存储在同一仓库中的两个或多个项目。在Yarn的词汇中,工作区是直接与项目相关的本地包。
  • 工作树 (Worktree): 是一个私有工作区,包含当前项目中的子工作区。
  • Yarn: 是一个用于管理编程环境的命令行工具。它用JavaScript编写,主要与JavaScript项目一起使用,但也有一些方面使其可以在多种情况下兼容使用。

Yarn的生命周期脚本

  • prepack是一个在所有调用yarn pack之前调用的生命周期脚本。
  • postpack可以在yarn pack之后调用,即使调用已完成或未完成。
  • prepublish可以在与yarn npm publish相同的命令之前调用。
  • postinstall可以在包的依赖树更改被写入磁盘后立即调用。

与npm的比较

  • Yarn并行安装所有包,而npm一次只安装一个包。
  • Yarn可以应用校验和来确保数据完整性,而npm应用SHA-512来检查下载包的数据完整性。
  • Yarn严格绑定包版本。
  • Yarn可以使用本地缓存安装包。

Yarn的架构

Node生态系统中,依赖项被放置在我们项目中的node_modules目录中。然而,这个文件结构可能与实际的依赖树不同,因为重复的依赖项会被合并。npm客户端会非确定性地将多个依赖项安装到node_modules目录中。这意味着目录结构,即node_modules,可能会因安装顺序的不同而在不同人之间有所差异。这些差异可能导致“我的机器上可以运行”的错误,需要花费时间去查找。

Yarn通过应用锁文件和可靠且确定的安装算法来解决非确定性和版本控制方面的问题。这些锁文件可以将(已安装的)依赖项锁定到特定版本,并确保在节点模块目录的所有机器上,所有安装输出都具有相同的文件结构。写入的锁文件采用紧凑的格式,并具有有序的键,以确保修改简单且易于审查。

安装过程分为三个不同的步骤,如下所述:

Install Yarn Ubuntu
  • 解析 (Resolution)- Yarn通过向注册表发起请求并递归查找所有依赖项来开始解析依赖项。
  • 获取 (Fetching)- Yarn接下来会在通用缓存目录中查找是否已安装所需的包。如果没有,Yarn会获取该包的tarball并将其存储在通用缓存中,以便可以离线使用,并且无需多次安装依赖项。此外,依赖项也可以放置在源代码控制中。
  • 链接 (Linking)- 最后,Yarn通过将所有必需的文件从通用缓存复制到本地目录,即node_modules,来完成链接。

通过清晰地划分这些步骤并具有确定的输出,Yarn可以并行化操作,从而提高资源利用率并加快安装过程。Yarn将Facebook的一些项目上的安装过程从几分钟缩短到几秒钟。此外,Yarn使用互斥锁来确保多个活动CLI实例不会互相污染和冲突。

Yarn在此整个过程中对包安装提供严格的保证。我们可以控制哪些生命周期脚本对哪些包运行。此外,包的校验和存储在锁文件中,以确保我们始终获得相同的包。

Yarn的安装架构

当我们运行yarn install命令时会发生什么,可以用几个不同的步骤来解释。

首先,我们输入“解析步骤”

  • 我们首先加载保存在锁文件中的条目,基于数据和最新的项目状态。核心执行内部算法来找出哪些条目不可用。
  • 对于所有缺失的条目,解析步骤通过Resolver接口查询插件,并询问它们是否知道与给定描述符相同的包。
  • 一旦依赖树中的所有包都已固定为元数据,核心将最后一次在内存中构建树以生成所谓的“虚拟包”。

解析步骤完成后,我们输入“获取步骤”

  • 现在我们拥有构成依赖树的相同包集,我们可以对其进行迭代,并对所有包,我们可以开始向缓存发起新的请求,以了解该包是否在任何地方可找到。如果不在,我们就按照上一步所做的操作,并查询我们的插件。
  • 关于获取器的有趣之处在于:它们通过fs的抽象层与核心进行协商。我们这样做是为了让我们的包可以来自不同的来源。对于通过注册表下载的包,可以是zip存档;对于portal:依赖项,可以是磁盘上的实际目录。

一旦所有包都准备好使用,最后就到了“链接步骤”

  • 我们使用的包应该以某种方式安装到磁盘上才能正常工作。
  • 这样做意味着可以很容易地为其他编程语言创建新的链接器——我们只需要编写关于Yarn提供的包应该发生什么的逻辑。
  • 另一个很酷的事情是,依赖树中的包不必都是同一种类型。我们的插件设计允许同时实例化多个链接器。包可以依赖于其他链接器。我们可以有一个依赖Python包的JavaScript包。

Yarn的组成部分

Yarn的四个主要组成部分列出并讨论如下:

Install Yarn Ubuntu
  • 客户端 (Client)- 负责提交MapReduce。
  • 资源管理器 (Resource manager)- 负责集群中的资源管理。
  • 节点管理器 (Node manager)- 负责在集群中引入和监控计算容器。
  • Map-reduce应用程序主控 (Map-reduce application master)- 负责检查所有正在运行的操作。应用程序主控在资源管理器和容器中实现,而节点管理器负责调度它。

使用Yarn的优点

以下是使用Yarn的一些主要优点,列出并解释如下:

Install Yarn Ubuntu
  • 速度 (Speed)- 缓存所有下载的包。它避免了以后重新下载的需要。Yarn还通过并行进程提高资源利用率,从而加快安装速度。
  • 安全性 (Security)- 通过校验和检查所有安装包的完整性。这在运行包代码之前完成。
  • 可靠性 (Reliability)- Yarn因其确定的安装方式和锁文件格式,在所有系统上提供基线安装。
  • 确定性 (Deterministic)- 无论安装顺序如何,相同的依赖项将在任何机器上以相同的方式安装。

以下是一些更多优点:

  • 支持bower和npm工作流,允许混合注册表
  • 用户可以限制已安装模块的许可证并提供许可证详细信息
  • 易于阅读的CLI输出
  • 离线模式允许在没有互联网连接的情况下重新安装包
  • 通过有效地排队请求(并忽略请求瀑布)来提高网络性能
  • 统一的安装结构,独立于安装顺序
  • 通过防止单个失败请求延迟整个安装来提高网络弹性,相反,失败的请求会自动重试。
  • 更多表情符号
  • 通过将不匹配的依赖版本解析为单个版本来消除重复。
  • 公开一致的公共JS API,并抽象日志记录供构建工具使用
  • 最小化、可读、美观的CLI输出
  • Yarn使用类bash的紧凑shell,使包脚本在macOS、Linux和Windows上保持紧凑。
  • Yarn是第一个可以以编程方式使用的Node API。
  • Yarn是完全类型检查的,并用TypeScript编写。
  • Yarn默认支持Node,但不仅限于此——插件还可以添加对多种其他语言的支持。

在Ubuntu上安装Yarn

Yarn是一个JavaScript包管理器,与npm兼容,可以自动化npm包的管理、更新、安装和卸载过程。它有助于捕获所有并行进程和下载的包,并加快安装过程。无论您是业余爱好者还是企业用户,都需要完成一次性项目,Yarn都能满足您的需求。

在本文中,我们将解释如何在Ubuntu上安装Yarn。

安装过程

我们可以按照以下步骤在Ubuntu系统中安装Yarn。

步骤1-更新系统存储库

我们需要按“Ctrl+Alt+T”打开Ubuntu终端窗口,并执行以下命令来更新系统存储库。


Install Yarn Ubuntu

步骤2-在Ubuntu上安装CURL

更新Ubuntu系统存储库后,我们需要运行以下命令来安装CURL。

以下结果表明我们已在系统中成功安装了CURL。

Install Yarn Ubuntu

步骤3-导入Yarn GPG密钥

在下一步中,我们需要使用“curl”命令将Yarn GPG密钥导入Ubuntu系统存储库。


Install Yarn Ubuntu

步骤4-启用Yarn存储库

导入Yarn GPG密钥后,我们需要在Ubuntu系统上启用Yarn存储库。为此,我们需要在终端窗口中使用以下命令。


Install Yarn Ubuntu

步骤5-在Ubuntu上安装Yarn

如果您已仔细遵循以上步骤,则您的Ubuntu系统已准备好进行Yarn的安装过程。我们需要运行以下命令来完成此操作。


Install Yarn Ubuntu

我们需要按“y”按钮以允许安装过程继续,并等待一段时间。

步骤6-检查Yarn版本

为了验证Yarn是否已成功安装,我们需要检查其在Ubuntu系统上的已安装版本。


Install Yarn Ubuntu

如下图所示,显示了当前安装在我们系统上的yarn版本。