Heim  >  Artikel  >  Web-Frontend  >  JavaScript-Paketmanager im Vergleich: Npm vs. Yarn vs. Pnpm

JavaScript-Paketmanager im Vergleich: Npm vs. Yarn vs. Pnpm

青灯夜游
青灯夜游nach vorne
2022-08-09 16:22:513092Durchsuche

Dieser Artikel führt Sie durch die drei JavaScript-Paketmanager (npm, Yarn, Pnpm), vergleicht diese drei Paketmanager und spricht über die Unterschiede und Beziehungen zwischen NPM, Yarn und PNPM. Ich hoffe, dass er für alle hilfreich ist hilft. Wenn Sie Fragen haben, weisen Sie sie bitte darauf hin!

JavaScript-Paketmanager im Vergleich: Npm vs. Yarn vs. Pnpm

Drei Hauptakteure im Bereich Paketmanager:

Eigentlich haben wir im Prinzip ähnliches Die Funktionalität ist in allen Paketmanagern implementiert. Daher werden Sie höchstwahrscheinlich aufgrund nichtfunktionaler Anforderungen, wie Installationsgeschwindigkeit, Speicherverbrauch oder Praktikabilität, entscheiden, welchen Paketmanager Sie verwenden möchten.

Natürlich ist die Art und Weise, wie Sie die einzelnen Paketmanager verwenden, unterschiedlich, aber im Grunde haben sie alle das gleiche Konzept. Alle oben genannten Paketmanager können die folgenden Befehle ausführen:

  • Daten lesen und schreiben
  • Alle Abhängigkeiten stapelweise installieren oder aktualisieren
  • Abhängigkeiten hinzufügen, aktualisieren und löschen
  • Skripte ausführen
  • Pakete veröffentlichen

Allerdings trotz Paketmanager sind unter der Haube unterschiedlich. Traditionell installieren npm und Yarn Abhängigkeiten in einem gekachelten node_modules-Ordner npmYarn 将依赖项安装在一个平铺的node_modules文件夹中。(这里注意先后顺序,是 yarn 先平铺的,之前 npm 是递归)。但是平铺也会造成一系列的安全问题。

  • 依赖结构的不确定性

  • 扁平化算法本身的复杂性很高,耗时较长。

  • 项目中仍然可以非法访问

  • 有声明过依赖的包

因此,pnpmnode_modules 文件夹中引入了一些新概念来更高效的存储依赖,。Yarn Berry 甚至通过完全放弃 node_modules 的 (PnP) 模式(另一个文章会具体说明)来走得更远。

JavaScript package简史


最早发布的包管理器是 npm,早在 2010 年 1 月。它就确立了今天包管理器工作的核心原则。但是既然 npm 已经存在 10 多年了,为什么还有其他选择?以下是出现这种情况的一些关键原因:

  • node_modules 文件夹结构的依赖关系解析算法不同(嵌套 & 平铺、node_modules vs. PnP mode)
  • 依赖提升方式不同(hoisting
  • locking 格式不同(性能都不同,比如 yarn 自己写的那一套)
  • 磁盘存储包文件方式不同(空间效率不同)
  • 多包项目(又名 workspaces)的支持不同,这会影响 monorepos 的可维护性和速度
  • 新工具和命令的需求不同(通过插件和社区工具对可扩展性的需求不同)
  • 可配置性和灵活性不同

让我们深入了解一下 npm 崛起后这些方面如何确定的历史,Yarn Classic 如何解决其中的一些问题,pnpm如何扩展这些概念,以及 Yarn Berry 作为 Yarn Classic 的继任者如何打破这些传统的概念和流程。

先驱者 npm

npm 是包管理器的鼻祖。许多人错误地认为 npm 是“Node package manager”的首字母缩写词,但事实并非如此

它的发布构成了一场革命,因为在此之前,项目依赖项都是手动下载和管理的。npm 引入了诸如文件及其元数据字段、将依赖项存储在node_modules, 自定义脚本, 公共和私有包等等。

2020 年,GitHub 收购了 npm,所以原则上 npm. (Achten Sie hier auf die Reihenfolge, yarn wird zuerst gekachelt, bevor npm rekursiv ist.) Aber Fliesen können auch eine Reihe von Sicherheitsproblemen mit sich bringen.

🎜Unsicherheit abhängiger Strukturen. 🎜🎜🎜🎜Der Flattening-Algorithmus selbst ist sehr komplex und dauert lange. 🎜🎜🎜🎜Es ist weiterhin möglich, illegalen Zugriff auf Pakete im Projekt zu erhalten, die Abhängigkeiten deklariert haben 🎜🎜🎜🎜 Daher ist pnpm drin node_modules Im Ordner werden einige neue Konzepte eingeführt, um Abhängigkeiten effizienter zu speichern. Yarn Berry geht sogar noch einen Schritt weiter, indem es den (PnP)-Modus von node_modules ganz aufgibt (ein anderer Artikel wird dies ausführlich erklären). 🎜

Eine kurze Geschichte des JavaScript-Pakets


🎜Der früheste veröffentlichte Paketmanager war npm, Anfang Januar 2010. Es legte die Grundprinzipien der heutigen Arbeitsweise von Paketmanagern fest. Aber warum gibt es Alternativen, da es npm schon seit über 10 Jahren gibt? Hier sind einige Hauptgründe, warum dies passiert:
🎜🎜🎜node_modules Unterschiedliche Abhängigkeitsauflösungsalgorithmen für Ordnerstrukturen (verschachtelt und flach, node_modules vs. PnP-Modus)🎜 🎜Unterschiedliche Methoden zum Heben von Abhängigkeiten (hoisting)🎜🎜locking hat unterschiedliche Formate (unterschiedliche Leistung, z. B. yarn, das ich selbst geschrieben habe)🎜🎜 Verschiedene Möglichkeiten, Paketdateien auf der Festplatte zu speichern (unterschiedliche Speicherplatzeffizienz)🎜🎜Die Unterstützung für Projekte mit mehreren Paketen (auch bekannt als Arbeitsbereiche) ist unterschiedlich, was sich auf die Monorepos auswirkt Wartbarkeit und Geschwindigkeit 🎜🎜 Unterschiedliche Anforderungen an neue Tools und Befehle (unterschiedliche Anforderungen an Erweiterbarkeit über Plugins und Community-Tools) 🎜🎜 Unterschiedliche Konfigurierbarkeit und Flexibilität 🎜🎜🎜 Schauen wir uns npm fest, wie <code>Yarn Classic einige dieser Probleme löste, wie pnpm diese Konzepte erweiterte und Yarn Berry > wie Der Nachfolger von Yarn Classic durchbricht diese traditionellen Konzepte und Prozesse. 🎜

Pioneer npm

🎜npm ist der Urheber von Paketmanagern. Viele Leute glauben fälschlicherweise, dass npm ein Akronym für „Node Package Manager“ ist, aber Das stimmt nicht 🎜. 🎜🎜 Die Veröffentlichung stellt eine Revolution dar, da zuvor Projektabhängigkeiten manuell heruntergeladen und verwaltet wurden. npm führt Dinge wie Dateien und ihre Metadatenfelder, das Speichern von Abhängigkeiten in node_modules, benutzerdefinierte Skripte, öffentliche und private Pakete und mehr ein. 🎜🎜Im Jahr 2020 hat GitHub npm übernommen🎜 , sodass npm im Prinzip jetzt von Microsoft verwaltet wird. Zum Zeitpunkt des Verfassens dieses Artikels ist die 🎜neueste Hauptversion v8🎜, veröffentlicht im Oktober 2021. 🎜

Innovator Yarn Classic

Im Oktober 2016 kündigte Facebook in Zusammenarbeit mit Google und einigen anderen Unternehmen einen neuen Paketmanager (engineering.fb.com/2016/10/11/…) an, um die Konsistenz und Sicherheit zu gewährleisten und Leistungsprobleme, die zu diesem Zeitpunkt bei npm auftraten. Sie nannten den Ersatz Garn.

Obwohl die Architektur und das Design von Yarn immer noch auf vielen Konzepten und Prozessen von npm basieren, hat Yarn einen erheblichen Einfluss auf den Verpackungsbereich gehabt Manager. Im Vergleich zu npm parallelisiert Yarn Vorgänge, um den Installationsprozess zu beschleunigen, was bei früheren Versionen von npm ein großes Problem darstellte. Yarn 还是基于 npm 的许多概念和流程来架构设计的,但 Yarn 还是对包管理器领域产生了重大影响。与 npm 相比,Yarn 并行化操作以加快安装过程,这一直是 npm 早期版本的主要痛点。

Yarn 为读写、安全性和性能设定了更高的标准,还发明了许多概念(后来npm也为此做了很多改进),包括:

  • monorepo 支持
  • 缓存安装
  • 离线下载
  • 文件锁(Locking

Yarn v1 于 2020 年进入维护模式 。从那时起,v1.x 系列被认为是旧版,并更名为 Yarn Classic。它的继任者 Yarn v2 (Berry) 现在是更加活跃的开发分支。

更高效的pnpm

pnpm 的第 1 版由 Zoltan Kochan于 2017 年发布。它是 npm 的替代品,所以如果你有一个 npm 项目,你可以马上使用 pnpm

创建 pnpm 的主要原因是 npmYarn 对于跨项目使用的依赖项存储结构非常冗余。尽管 Yarn Classicnpm 具有速度优势,但它使用相同的依赖解析方法,这对 pnpm 来说是不行的:npmYarn Classic 使用 hoisting 来平铺他们的 node_modules.

pnpm 没有优化之前的结构,而是引入了另一种依赖解决策略:内容寻址的一种存储结构。此方法生成的 node_modules 文件夹其实是依赖于全局存储在主文件夹上的 ~/.pnpm-store/ 目录。每个版本的依赖项都物理形式存储在该目录文件夹中一次,构成单一的源地址来节省相当多的磁盘空间。

node_modules 结构是通过使用 symlinks 创建依赖关系的嵌套结构(其中文件夹内每个文件/包都是通过硬链接存储)官方文档中的下图阐明了这一点。(待填坑:软硬链接)

JavaScript-Paketmanager im Vergleich: Npm vs. Yarn vs. Pnpm

2021 年报告中可见 pnpm 的影响力:因为他们在内容可寻址存储方面的创新,竞争对手都希望采用 pnpm 的概念,比如象征性链接的结构和包的高效磁盘管理。

Yarn (v2, Berry),用 Plug'n'Play 重新发明的轮子

Yarn 2于 2020 年 1 月发布,被宣传为原始 Yarn 的重大升级。Yarn 团队将其称为 Yarn Berry

Yarn setzte höhere Standards für Lesen und Schreiben, Sicherheit und Leistung und erfand viele Konzepte (später nahm npm auch viele Verbesserungen hierfür vor), einschließlich: 🎜
  • monorepo unterstützt
  • zwischengespeicherte Installation
  • Offline-Download
  • Dateisperrung (Sperren )
🎜Yarn v1 im Jahr 2020 🎜Wartungsmodus aufrufen 🎜 . Seitdem gilt die v1.x-Serie als Legacy und wurde in Yarn Classic umbenannt. Sein Nachfolger Yarn v2 (Berry) ist nun der aktivere Entwicklungszweig. 🎜

🎜Effizienteres pnpm🎜🎜🎜Version 1 von pnpm von Zoltan Kochan🎜 wurde 2017 veröffentlicht. Es ist ein Ersatz für npm. Wenn Sie also ein npm-Projekt haben, können Sie pnpm sofort verwenden! 🎜🎜Der Hauptgrund für die Erstellung von pnpm ist, dass npm und Yarn für projektübergreifende Abhängigkeitsspeicherstrukturen sehr redundant sind. Obwohl Yarn Classic einen Geschwindigkeitsvorteil gegenüber npm hat, verwendet es dieselbe Methode zur Abhängigkeitsauflösung, was mit pnpm nicht möglich ist: npm und Yarn Classic verwenden hoisting, um ihre node_modules zu kacheln. 🎜🎜pnpm optimiert nicht das vorherige Struktur, stattdessen wird eine andere Strategie zur Abhängigkeitsauflösung eingeführt: Ein Speicher Struktur der inhaltlichen Ansprache 🎜. Der durch diese Methode generierte Ordner node_modules basiert tatsächlich auf dem Verzeichnis ~/.pnpm-store/, das global im Hauptordner gespeichert ist. Jede Version von Abhängigkeiten wird physisch einmal in diesem Verzeichnisordner gespeichert und bildet so eine einzige Quelladresse, um erheblich Speicherplatz zu sparen. 🎜🎜Die node_modules-Struktur ist eine verschachtelte Struktur von Abhängigkeiten, die mithilfe von symlinks erstellt wurden (wobei jede Datei/jedes Paket im Ordner über Hard Links 🎜 Storage) Das folgende Bild aus der offiziellen Dokumentation verdeutlicht dies. (Zu füllen: Soft- und Hardlinks) 🎜🎜 JavaScript-Paketmanager im Vergleich: Npm vs. Yarn vs. Pnpm🎜🎜2021 Report🎜 Der Der Einfluss von pnpm kann im Die Struktur symbolischer Links 🎜 und effiziente Festplattenverwaltung von Paketen. 🎜

Garn (v2, Berry), das Rad mit Plug'n'Play neu erfinden🎜🎜Yarn 2🎜 wurde im Januar 2020 veröffentlicht und als großes Upgrade des ursprünglichen Yarn beworben. Das Yarn-Team nannte es Yarn Berry, um deutlicher zu machen, dass es sich im Wesentlichen um einen neuen Paketmanager mit einer neuen Codebasis und neuen Prinzipien handelt. 🎜Die wichtigste Innovation von

Yarn Berry ist sein Plug-and-Play (PnP) Yarn Berry 的主要创新是其即插即用 (PnP)方法,它是作为修复node_modules的策略。不是生成node_modules 的策略,而是生成一个带有依赖查找表的文件 .pnp.cjs,因为它是单个文件而不是嵌套的文件夹结构,所以可以更有效地处理依赖。此外,每个包都以zip 文件的形式存储在文件夹内来替代 .yarn/cache/,占用的磁盘空间也比 node_modules 少。

所有这些变化如此之快以至于在发布后引起了很大的争议。PnP 这种破坏性的重大更改要求维护者更新他们现有的包以便与其兼容。默认情况下使用全新的 PnP 方法并且恢复到 node_modules 最初并不简单,这导致许多知名开发人员没有加入其中的考虑且公开批评 Yarn 2

此后,Yarn Berry 团队在其后续版本中解决了许多问题。为了解决 PnP 的不兼容问题,团队提供了方法来轻松更改默认操作模式。在node_modules插件的帮助下,切换回传统  node_modules 方法只需要一行配置。

此外,随着时间的推移,JavaScript 生态系统为 PnP 提供了越来越多的支持,正如您在此兼容性表中所见,一些大型项目已经开始采用 Yarn Berry

尽管 Yarn Berry 还很年轻,但它也已经对包管理器领域产生了影响——pnpm 在 2020 年末采用了PnP 方法

安装工作流程


首先必须在每个开发人员的本地和 CI/CD 系统上安装包管理器。

npm

npmNode.js 一起提供,因此不需要额外的步骤。除了为您的操作系统下载Node.js 安装程序外,使用 CLI 工具管理软件版本已成为一种常见做法。在 Node 的上下文中,Node Version Manager (nvm)Volta 已成为非常方便的实用程序。

Yarn Classic 和 Yarn Berry

您可以通过不同的方式安装 Yarn 1,例如,作为 npm 包来安装:.$ npm i -g yarn

要从Yarn Classic 迁移到 Yarn Berry,推荐的方法是:

  • 安装或更新 Yarn Classic-Methode, es handelt sich um eine Fixing node_modules

    -Strategie . Anstelle der Strategie, node_modules zu generieren, generieren Sie eine Datei .pnp.cjs mit einer Abhängigkeits-Nachschlagetabelle, da es sich um eine einzelne Datei und nicht um eine verschachtelte Ordnerstruktur, also Abhängigkeiten, handelt effizienter gehandhabt werden können. Darüber hinaus beginnt jedes Paket mit dem Ziel Zip-Datei
  • wird im Ordner anstelle von .yarn/cache/ gespeichert und nimmt weniger Speicherplatz ein als einige wenige node_modules .
  • Alle diese Änderungen erfolgten so schnell, dass sie nach der Veröffentlichung für große Kontroversen sorgten. PnP Diese bahnbrechende bahnbrechende ÄnderungBitten Sie die Betreuer, ihre vorhandenen Pakete

    zu aktualisieren, damit sie mit ihnen kompatibel sind. Die standardmäßige Verwendung des neuen PnP-Ansatzes und die Rückkehr zu node_modules war anfangs nicht einfach, was dazu führte, dass viele bekannte Entwickler nicht darüber nachdachten, mitzumachen und Garn 2 öffentlich kritisieren
  • .

Seitdem hat das Yarn Berry-Team Viele Probleme gelöst. Um PnP-Inkompatibilitätsprobleme zu beheben, hat das Team eine Möglichkeit bereitgestellt, den Standardbetriebsmodus einfach zu ändern. Wechseln Sie mit Hilfe des node_modules-Plugins zurück zum traditionellen Modus Die Methode node_modules erfordert nur eine Konfigurationszeile.

🎜 Darüber hinaus bietet das JavaScript-Ökosystem im Laufe der Zeit immer mehr Unterstützung für PnP, wie Sie hier sehen können Wie in der Kompatibilitätstabelle 🎜 zu sehen ist, einigeGroß 🎜Projekt 🎜 hat mit der Einführung von Yarn Berry begonnen. 🎜🎜Obwohl Yarn Berry noch jung ist, hat es bereits Auswirkungen auf den Paketmanagerbereich gehabt – pnpm wurde PnP method 🎜. 🎜

Installationsworkflow


🎜Paketverwaltung muss zuerst auf dem lokalen und CI/CD-Systemgerät jedes Entwicklers installiert werden.
🎜

npm

🎜npm zusammen mit Node.js bereitgestellt, so dass keine zusätzlichen Schritte erforderlich sind. Verwenden Sie zusätzlich zum Herunterladen des
Node.js Installer 🎜 für Ihr Betriebssystem die CLI Tools zur Verwaltung von Softwareversionen sind mittlerweile gängige Praxis. Im Kontext von Node: Node Version Manager (nvm)🎜 oder Volta🎜 ist zu einem sehr praktischen Dienstprogramm geworden. 🎜

Yarn Classic und Yarn Berry

🎜Sie können es auf verschiedene Arten machen
Installieren Sie Yarn 1🎜, zum Beispiel als npm-Paket: .$ npm i -g Yarn🎜🎜Zur Migration von Yarn Classic Für Yarn Berry🎜 lautet die empfohlene Methode: 🎜
    🎜🎜Installieren oder aktualisieren Sie Yarn Classic auf die neueste Version🎜🎜🎜🎜Verwenden Sie den Befehl, um auf die neueste moderne Version zu aktualisieren🎜
yarn set version berry
🎜🎜 🎜Aber die 🎜empfohlene Methode zur Installation von Yarn Berry🎜 ist Corepack. 🎜

Corepack是由 Yarn Berry 的开发者创建的。该计划最初被命名为包管理器管理器(pmm) ?,并在 LTS v16 中与 Node 合并。

在 Corepack 的帮助下,因为 Node 包含 Yarn ClassicYarn Berrypnpm 二进制文件所以您不必“单独”安装的 npm 的替代包管理器。这些垫片允许用户运行 Yarn 和 pnpm 命令而无需先显式安装它们,也不会弄乱 Node 发行版。

Corepack 预装了 Node.js ≥ v16.9.0。但是,对于较旧的 Node 版本,您可以使用⬇️

npm install -g corepack

在使用之前先启用 Corepack。该示例显示了如何在 Yarn Berry v3.1.1 中激活它。

# you need to opt-in first
$ corepack enable
# shim installed but concrete version needs to activated
$ corepack prepare yarn@3.1.1 --activate

pnpm

您可以将 pnpm 作为 npm包来安装: $ npm i -g pnpm。您还可以使用 Corepack 安装 pnpm : 

$ corepack prepare pnpm@6.24.2 --activate

项目结构


在本节中,您将一目了然地看到不同包管理器的主要特征。您可以轻松发现配置特定包管理器涉及哪些文件,以及哪些文件是由安装步骤生成的。

所有包管理器都将所有重要的元信息存储在项目清单package.json文件中。 此外,根级别的配置文件可以被用来设置不同的私有包或者不同的依赖项解析配置。

在安装步骤中,依赖项 dependencies 被存储在文件结构中,例如 node_modules 并生成锁定文件 locking。本节不考虑工作区设置,因此所有示例仅显示存储依赖项的单个位置。

npm

使用$ npm install 或较短的 $ npm i 会生成一个 package-lock.json 文件和一个 node_modules 文件夹。还有 .npmrc 这种可配置的文件可以放在根级别目录里面。有关 locking 文件的更多信息,请参阅下一节。

.
├── node_modules/
├── .npmrc
├── package-lock.json
└── package.json

yarn

运行 $ yarn 会创建一个 yarn.lock 文件和一个 node_modules 文件夹。.yarnrc 文件也可以是配置的选项,Yarn Classic 也支持 .npmrc 文件。或者可以使用缓存文件夹 .yarn/cache/ 和本地存储的最近的 Yarn Classic 版本 .yarn/releases/

.
├── .yarn/
│   ├── cache/
│   └── releases/
│       └── yarn-1.22.17.cjs
├── node_modules/
├── .yarnrc
├── package.json
└── yarn.lock

yarn berry: node_modules

因为这种特殊的安装模式,比使用其他包管理器您必须在 Yarn Berry 项目中处理更多的文件和文件夹。有些是可选的,有些是强制性的。

Yarn Berry 不再支持 .npmrc 或者 .yarnrc;他需要一个 .yarnrc.yml。对于传统的生成 node_modules 文件夹的工作流程,您必须提供 nodeLinker 配置来使用 node_modules 或者 pnpm 的配置(这块没看懂)。

# .yarnrc.yml
nodeLinker: node-modules # or pnpm

运行 $ yarn 会将所有依赖项安装在一个 node_modules 文件夹中。并且生成一个 yarn.lock 文件,该文件较新但与 Yarn Classic 不兼容。此外,还会生成一个用于离线安装的 .yarn/cache/ 文件夹。该文件夹是可选的,用于存储项目使用的 Yarn Berry 版本。

.
├── .yarn/
│   ├── cache/
│   └── releases/
│       └── yarn-3.1.1.cjs
├── node_modules/
├── .yarnrc.yml
├── package.json
└── yarn.lock

yarn berry: pnp

无论是对于PnP 的严格模式还是松散模式,跟着 .pnp.cjsyarn.lock 来执行 $ yarn 都会生成一个 .yarn/cache/ 还有 .yarn/unplugged。PnP strict 是默认模式,如果想要配置 loose 模式,需要如下形式开启⬇️:

# .yarnrc.yml
nodeLinker: pnp
pnpMode: loose

在 PnP 项目中,除了 releases 文件夹之外,.yarn 文件夹很可能还包含一个提供IDE 支持的 sdk/ 文件夹。根据您的用例,.yarn 甚至可以包含更多的文件夹。

.
├── .yarn/
│   ├── cache/
│   ├── releases/
│   │   └── yarn-3.1.1.cjs
│   ├── sdk/
│   └── unplugged/
├── .pnp.cjs
├── .pnp.loader.mjs
├── .yarnrc.yml
├── package.json
└── yarn.lock`

pnpm

npmYarn Classic 项目的初始状态一样,pnpm 也需要 package.json 文件。使用 $ pnpm i 安装依赖项后,会生成一个 node_modules 文件夹,但由于其内容是可寻址存储方式,其结构完全不同。

pnpm 还会生成自己的锁定文件 pnp-lock.yml。 您可以使用可选文件 .npmrc 提供附加配置。

.
├── node_modules/
│   └── .pnpm/
├── .npmrc
├── package.json
└── pnpm-lock.yml

锁定文件和依赖存储


如上一节所述,每个包管理器都会创建锁定文件

lock 文件准确存储您的项目安装的每个依赖项的版本从而实现更可预测和确定性的安装。因为依赖版本很可能使用版本范围声明(例如,≥ v1.2.5)所以这个 lock 文件是很重要的,如果您不“lock”您的版本,实际安装的版本可能会有所不同。

锁定文件有时也存储校验和(我记得是一段hash),我们将在安全部分更深入地介绍。

npm v5+ 开始锁定文件一直是 npm 主要的功能 ( package-lock.json ) ,pnpm 里是 pnpm-lock.yaml ,在 Yarn Berry 中的 yarn.lock 以新的 YAML 格式出现。

在上一节中,我们看到了传统方法,将依赖项安装在 node_modules 文件夹结构中。这是 npmYarn Classicpnpm都使用的方案,(其中 pnpm 比其他方案更有效)。

Yarn Berry 在 PnP 模式下的做法有所不同。依赖项不是 node_modules 文件夹,而是以 zip 文件的形式存储为 .yarn/cache/.pnp.cjs 文件的组合。

最好将这些锁定文件置于版本控制之下,因为每个团队成员都安装相同的版本,所以它解决了“在你和我的机器上工作”问题。

CLI


下表比较了 npmYarn ClassicYarn Berrypnpm 中可用的不同 CLI 命令。这绝不是一个完整的列表,而是一个备忘单。本节不涉及与workflow 相关的命令。

npmpnpm 具有许多特别的命令和选项别名,这意味着命令可以有不同的名称,即$ npm install$ npm add。 此外,许多命令选项都有缩写版本,例如 -D 来代替 --save-dev。 在表格中,我将所有缩写版本称为别名。使用这些包管理器,您都可以增加、更新或删除多个依赖项。

依赖配置管理

此表涵盖了用于安装或更新 package.json 中指定的所有依赖项的依赖项管理命令。

重要的是要理解,Yarn Berry 只允许我们执行在 package.json 中或者暴露在 bin/ Jetzt herunterladen的指定的二进制文件.ActionnpmYarn ClassicYarn.Berry
Action npm Yarn Classic Yarn Berry pnpm
deps in package.json installieren npm-Installationsalias: i, hinzufügen Garninstallation oder Garn like Classic pnpm install alias: i
update deps in package.json gem. semver npm-Update-Alias: up, upgrade yarn upgrade yarn semver up (über plugin) pnpm-Update-Alias: up
update deps in package.json auf den neuesten Stand N/A yarn upgrade --latest yarn up pnpm update --latest alias: -L
update deps gem. semver npm update react yarn upgrade react yarn semver up react pnpm up react
update deps zu letztendlich npm update react@last yarn upgrade react -latest yarn up reag pnpm up -L reagieren
Deps interaktiv aktualisieren N/A Garn-Upgrade-interaktiv Garn-Upgrade-interaktiv (über Plugin) $ pnpm up --interaktiver Alias: -i
Laufzeit-Deps hinzufügen npm ich reagiere yarn füge React hinzu like Classic pnpm füge React hinzu
Dev-Deps hinzufügen npm i -D babel alias: --save-dev yarn hinzufügen -D Babel-Alias: --dev like Classic pnpm -D Babel-Alias ​​hinzufügen: --save-dev
Deps zu package.json ohne Semver hinzufügen npm i -E Reaktionsalias: --save -exact yarn add -E React Alias: --exact like Classic pnpm add -E React Alias: --save-exact
Deps deinstallieren und aus package.json entfernen npm React Alias ​​deinstallieren : Remove, RM, R, Un, Unlink -nicht gespeichert何在开发期间管理包.表中使用的术语: Paket: Abhängigkeit oder Binär Binär: 一种执行工具来自 node_modules/.bin/ 或者 .yarn/cache/ (PnP)

install Pakete global

npm i -g ntl Alias: --global

yarn Global Add Ntl
  • n/A (
  • Global entfernt)
  • node_modules/.bin/ 或者 .yarn/cache/ (PnP)

重要的是要理解,Yarn Berry 只允许我们执行在 package.json 中或者暴露在 bin/pnpm hinzufügen --global ntl

update Pakete Global update --global ntlPakete global entfernennpm deinstallieren -g ntlyarn global ntl entfernenN/Apnpm entfernen --global ntlBinärdateien ausführen von. terminaln PM Exec ntlyarn ntlpnpm ntlBinärdateien aus dem Skript ausführenntlntlntlntldynamisches Paket Ausführungnpx ntlN/Ayarn dlx ntlpnpm dlx ntlruntime deps hinzufügennpm ich reagiereyarn add reactlike Classicpnpm add reagierendev deps hinzufügen npm i -D babel alias : --save-devyarn add -D babel alias: --devlike Classicpnpm add -D babel alias: --save-devadd deps to package.json without semver npm i -E reagierender Alias: --save-exactyarn add -E reagierender Alias: --exactlike Classicpnpm add -E reagierender Alias: --save-exactdeps deinstallieren und entfernen aus package.jsonnpm uninstall React Alias: Remove, RM, R, Un, UnlinkYarn Remove Reactlike Classicpnpm Remove React Alias: rm, Un, UninstallDeps ohne deinstallieren Aktualisierung von package.jsonnpm uninstall --no-saveN/AN/AN/A

Häufig verwendete Befehle

Diese Tabelle behandelt einige nützliche integrierte Befehle. Wenn es keinen offiziellen Befehl gibt, können Befehle von Drittanbietern normalerweise über npm 包或 Yarn Berry Plugins verwendet werden.

yarn ntl
npm erklären NTL-Alias: WarumGarn, warum NTLwie ClassicPNPM, warum NTLInit-Projektnpm init -y npm init. (inter aktiv) alias s : --yesyarn init -y Yarn init (interaktiv) Alias: --yesyarn initpnpm init -y pnpm init (interaktiv) Alias: --yesDrucklizenzinformationenN / A (über Drittanbieterpaket)GarnlizenzlisteN/A (oder über , anderes )N/A (über Drittanbieterpaket)Paketmanager aktualisieren Version N/A (mit Tools von Drittanbietern, z. B. nvm)mit npm: Garnrichtlinien-Set-Version 1.13.0mit Corepack: Garnset-Version 3.1.1N/A (mit npm, Corepack) npm Audityarn Audityarn NPM Auditpnpm Auditadd DEPs an package.json ohne Semvernpm i -e React alias: -Save - ExactYarn Add -E React Alias: --exactlike Classicpnpm Add -E React Alias: --save-exactdeps deinstallieren und aus package.json entfernennpm React Alias ​​deinstallieren : Remove, RM, R, Un, Unlink - nicht gespeichertN/AN/AN/A

配置文件


配置包管理器发生在您的 package.json 和专用的配置文件中。

  • 定义要使用的准确版本
  • 使用特定的依赖解决策略
  • 配置私有注册表
  • 告诉包管理器在哪里可以找到 monorepo 中的工作区

npm

大多数配置发生在专用配置文件 .npmrc 中。

如果你想使用 npmworkspaces 功能,你必须在 package.json 中添加workspaces 元数据字段来告诉 npm 在哪里可以找到子项目或工作空间的文件夹。

  // ...
  "workspaces": [
    "hooks",
    "utils"
  ]
}

每个包管理器都可以使用公共 npm 注册表。或许你很可能希望重用它们而不将它们发布到公共注册表。您可以在 .npmrc 文件中执行此操作配置来私有注册表。( 现在基本都有私有源了)

# .npmrc
@doppelmutzi:registry=https://gitlab.doppelmutzi.com/api/v4/projects/41/packages/npm/

npm 存在许多配置选项,最好在文档中查看它们。\

yarn

您可以在 package.json 中设置 yarnworkspaces(必须是私有包)。

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

任何可选配置都进入一个 .yarnrc 文件。一个常见的配置选项是设置一个 yarn-path: 它强制每个团队成员使用指定的二进制版本。yarn-path 指向包含特定 Yarn 版本的文件夹(例如 .yarn/releases/)。您可以使用命令来安装统一的 Yarn Classic 版本(classic.yarnpkg.com/en/docs/cli…)。

yarn berry

Yarn Berry 中配置 workspaces 和在 Yarn Classic 中的配置方式类似(package.json)。 大多数 Yarn Berry 配置发生在 .yarnrc.yml 中,并且有许多可用的配置选项。

# .yarnrc.yml
yarnPath: .yarn/releases/yarn-3.1.1.cjs

yarn berry可以用 $> yarn plugin import <name></name> 这种导入方式来扩展插件(yarnpkg.com/cli/plugin/…),这个命令也会更新 .yarnrc.yml

# .yarnrc.yml
plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-semver-up.cjs
    spec: "https://raw.githubusercontent.com/tophat/yarn-plugin-semver-up/master/bundles/%40yarnpkg/plugin-semver-up.js"

如历史部分所述,因为兼容性的关系,PnP 严格模式下的依赖关系可能存在某些问题。此类 PnP 问题有一个典型的解决方案:包扩展配置策略

# .yarnrc.yml
packageExtensions:
  "styled-components@*":
    dependencies:
      react-is: "*"

pnpm

pnpm 使用与 npm 相同的配置机制,因此您可以使用 .npmrc 文件。配置私有注册表的工作方式也与使用 npm 相同。借助 pnpm 的工作空间功能可以支持多包项目。要初始化 monorepo,您必须在 pnpm-workspace.yaml 文件中指定包的位置

# pnpm-workspace.yaml
packages:
  - 'packages/**'

Monorepo


什么是Monorepo

(这里其实就是三种概念,单仓库多项目,单仓库单项目,多仓库多项目)

monorepo 是一个包含多个项目的存储库,这些项目被称为 workspace 或者包。将所有内容保存在一个地方而不是使用多个存储库是一种项目组织策略。

当然,这会带来额外的复杂性。Yarn Classic 是第一个启用此功能的,但现在每个主要的包管理器都提供了工作区功能。本节展示如何使用每个不同的包管理器配置工作区。

npm

npm 团队在 v7 中发布了期待已久的npm 工作区功能。它包含许多 CLI 命令,可帮助从根包中管理多包项目。大多数命令可以与 workspace 相关的选项一起使用以告诉 npm 它是否应该针对特定、多个或所有工作空间运行。

# Installing all dependencies for all workspaces
$ npm i --workspaces.
# run against one package
$ npm run test --workspace=hooks
# run against multiple packages
$ npm run test --workspace=hooks --workspace=utils
# run against all
$ npm run test --workspaces
# ignore all packages missing test
$ npm run test --workspaces --if-present

tips: 与其他包管理器相比,npm v8 目前不支持高级过滤或并行执行多个与工作区相关的命令。

yarn

2017 年 8 月,Yarn 团队宣布在workspace功能方面提供 monorepo 支持。在此之前,只能在Lerna等第三方软件的多包项目中使用包管理器。Yarn 的这一新增功能也为其他包管理器实现此类功能铺平了道路。

如果你有兴趣,可以参考如何在有和没有 Lerna 的情况下使用 Yarn Classic 的工作区功能。但是这篇文章只会介绍一些必要的命令,以帮助您管理 Yarn Classic 工作区设置中的依赖关系。

# 为所有工作空间安装所有依赖项
$ yarn 
# 显示依赖关系树
$ yarn workspaces info 
# 再一个包运行启动
$ yarn workspace awesome - package start
  # 将Webpack添加到包
$ yarn workspace awesome - package add - D webpack
  # add React 对所有包
$ yarn add react -W

yarn berry

Yarn Berry 从一开始就以工作区为特色,因为它的实现是建立在 Yarn Classic 的概念之上的。在Reddit 评论中,Yarn Berry 的主要开发人员简要概述了面向工作空间的功能,包括:

Yarn Berry 使用大量可用于 package.json 文件的 dependenciesdevDependencies 字段的协议。其中就有 workspace协议

Yarn Classic 的工作区相比,Yarn Berry 明确定义依赖项必须是此 monorepo 中的包之一。否则如果版本不匹配,Yarn Berry 可能会尝试从远程注册表获取其版本。

{
  // ...
  "dependencies": {
    "@doppelmutzi/hooks": "workspace:*",
    "http-server": "14.0.0",
    // ...
  }  
}

pnpm

通过 workspace 这种协议,pnpm 促成了类似于 Yarn Berrymonorepo 项目。许多 pnpm 命令接受 --recursive (-r) 或者 --filter 这种在 monorepo 上下文中特别有用的选项。它的原生过滤命令也是对 Lerna 的一个很好的补充。

# prune all workspaces  
pnpm -r exec -- rm -rf node_modules && rm pnpm-lock.yaml  
# run all tests for all workspaces with scope @doppelmutzi
pnpm recursive run test --filter @doppelmutzi/`

性能 & 磁盘效率


性能是选型决策的关键部分。本节展示了基于一个小型和一个中型项目的基准测试。以下是有关示例项目的一些说明:

  • 两组基准都不使用工作区功能
  • 小项目指定33个依赖
  • 中项目指定44个依赖

我用三个用例 (UC) 对我们的每个包管理器变体进行了一次测量。要了解详细的评估和解释,请查看项目 1 (P1)项目 2 (P2)的结果。

  • UC 1:没有缓存/存储,没有锁定文件,没有 node_modules.pnp.cjs
  • UC 2:存在缓存/存储,没有锁定文件,没有 node_modules.pnp.cjs
  • UC 3:存在缓存/存储,存在锁定文件,没有 node_modules.pnp.cjs

我使用工具gnomon来测量安装消耗的时间( yarn | gnomon )。此外我测量了生成文件的大小 $ du -sh node_modules

Action npm Yarn Classic Yarn Berry pnpm
Publish npmPublish YarnPublish Yarn NPM Publish PNPM Publish
Liste installiert deps rn upgrade-interaktiv pnpm veraltet Informationen über Deps drucken
PluginPlugin
Perform Security Audit
Performance results for Project 1






Method npm v8.1.2 Yarn Classic v1.23.0 pnpm v6.24.4 Yarn Berry PnP loose v3.1.1 Yarn Berry PnP strict v3.1.1 Yarn Berry node_modules v3.1.1 Yarn Berry pnpm v3.1.1
UC 1 86.63s 108.89s 43.58s 31.77s 30.13s 56.64s 60.91s
UC 2 41.54s 65.49s 26.43s 12.46s 12.66s 46.36s 40.74s
UC 3 23.59s 40.35s 20.32s 1.61s 1.36s 28.72s 31.89s
Files and size package-lock.json: 1.3M node_modules: 467M node_modules: 397M yarn.lock: 504K pnpm-lock.yaml: 412K node_modules: 319M yarn.lock: 540K cache: 68M unplugged: 29M .pnp.cjs: 1.6M yarn.lock: 540K cache: 68M unplugged: 29M .pnp.cjs: 1.5M node_modules: 395M yarn.lock: 540K cache: 68M node_modules: 374M yarn.lock: 540K cache: 68M
Performance results for Project 2






Method npm v8.1.2 Yarn Classic v1.23.0 pnpm v6.24.4 Yarn Berry PnP loose v3.1.1 Yarn Berry PnP strict v3.1.1 Yarn Berry node_modules v3.1.1 Yarn Berry pnpm v3.1.1
UC 1 34.91s 43.26s 15.6s 13.92s 6.44s 23.62s 20.09s
UC 2 7.92s 33.65s 8.86s 7.09s 5.63s 15.12s 14.93s
UC 3 5.09s 15.64s 4.73s 0.93s 0.79s 8.18s 6.02s
Files and size package-lock.json: 684K node_modules: 151M yarn.lock: 268K node_modules: 159M pnpm-lock.yaml: 212K node_modules: 141M .pnp.cjs: 1.1M .pnp.loader.mjs: 8.0K yarn.lock: 292K .yarn: 38M .pnp.cjs: 1.0M .pnp.loader.mjs: 8.0K yarn.lock: 292K .yarn: 38M yarn.lock: 292K node_modules: 164M cache: 34M yarn.lock: 292K node_modules: 156M cache: 34M

Sicherheit


npm

npm ist im Umgang mit fehlerhaften Paketen etwas zu nachsichtig und hat einige Sicherheitslücken festgestellt, die sich direkt auf viele Projekte ausgewirkt haben. Wenn Sie beispielsweise in Version 5.7.0 den Befehl sudo npm auf einem Linux-Betriebssystem ausführen, können Sie Eigentum an Systemdateien ändernnpm 在处理坏包时有点过于宽容并且遇到了一些直接影响许多项目的安全漏洞。例如,在 5.7.0 版本中,当您在 Linux 操作系统上执行 sudo npm 命令时,可以更改系统文件的所有权,从而导致操作系统无法使用。

另一起事件发生在 2018 年,涉及比特币被盗。 Node.js 包EventStream在其 3.3.6 版本中添加了恶意依赖项。这个恶意包包含一个加密方法试图从开发者的机器上窃取比特币。

为了帮助解决这些问题,新的 npm 版本使用密码算法来检查您安装的软件包的完整性。SHA-512

yarn

Yarn ClassicYarn Berry 从一开始就使用校验和来检验每一个包的完整性。Yarn 还试图阻止您检索在 package.json 中未声明的恶意包:如果发现不匹配,则中止安装。

PnP 模式下的 Yarn Berry 没有传统 node_modules 方式的安全问题。与 Yarn Classic 相比,Yarn Berry 提高了命令执行的安全性。您只能执行已在 package.json 声明的包。此安全功能类似于 pnpm,我将在下面进行描述。

pnpm

pnpm 还是使用校验和来验证每个已安装包的完整性,然后再执行其代码。

正如我们在上面提到的,npmYarn Classic 都存在由于提升而导致的安全问题pnpm 避免了这种情况,因为它的管理模型不使用提升;相反,它会生成嵌套 node_modules 文件夹,从而消除非法依赖访问的风险。这意味着依赖关系都在 .package.json 中声明了。

正如我们所讨论的,这在 monorepo, wodurch das Betriebssystem unbrauchbar wird. Ein weiterer Vorfall Der Vorfall

ereignete sich im Jahr 2018 und beinhaltete den Diebstahl von Bitcoin. Das Node.js-Paket EventStream🎜fügte in seiner Version 3.3.6 eine bösartige Abhängigkeit hinzu. Dieses Schadpaket enthält eine kryptografische Methode, die versucht, Bitcoins vom Computer des Entwicklers zu stehlen. 🎜🎜Um diese Probleme zu beheben, verwendet die neue npm-Version CryptoAlgorithm 🎜, um die Integrität Ihrer installierten Pakete zu überprüfen. SHA-512🎜. 🎜

🎜yarn🎜🎜🎜Yarn Classic und Yarn Berry werden von Anfang an verwendet Checksum🎜, um die Integrität jedes Pakets zu überprüfen. Yarn versucht außerdem, Sie daran zu hindern, schädliche Pakete abzurufen, die nicht in package.json deklariert sind: Wenn eine Nichtübereinstimmung festgestellt wird, wird die Installation abgebrochen. 🎜🎜Der PnP-Modus Yarn Berry weist nicht die Sicherheitsprobleme des herkömmlichen node_modules-Ansatzes auf. Im Vergleich zu Yarn Classic verbessert Yarn Berry die Sicherheit der Befehlsausführung. Sie können nur Pakete ausführen, die in package.json deklariert wurden. Diese Sicherheitsfunktion ähnelt pnpm, das ich unten beschreibe. 🎜

🎜pnpm🎜🎜🎜pnpm oder Verwenden Sie die Prüfsumme 🎜, um die Integrität jedes installierten Pakets zu überprüfen, bevor Sie dessen Code ausführen. 🎜🎜Wie oben erwähnt, gibt es sowohl npm als auch Yarn Classic Verursacht durch Sicherheitsprobleme bei der Werbeaktion 🎜. pnpm vermeidet diese Situation, da sein Verwaltungsmodell keine Heraufstufung verwendet; es generiert stattdessen verschachtelte node_modules-Ordner und eliminiert so das Risiko eines illegalen Abhängigkeitszugriffs. Dies bedeutet, dass Abhängigkeiten in .package.json deklariert werden. 🎜🎜Wie wir besprochen haben, ist dies besonders wichtig in einer Monorepo-Umgebung, da Boosting-Algorithmen manchmal zu „abhängigem Nichtdeterminismus“ führen können. 🎜

Beliebte Projektnutzung


Apollo Server




npm Yarn Classic Yarn Berry pnpm
Svelte React Jest (mit node_modules) Vue 3
Preact Angular Storybook (mit node._modules ) Browserliste
Express .js Ember Babel (mit node_modules) Prisma
Meteor Weiter ux Toolkit (mit node_modules) SvelteKit
Gatsby

Nuxt


React App erstellen


webpack-cli


Emotion


Fazit


Es gibt tatsächlich große Unterschiede in den Prinzipien verschiedener Paketmanager.

pnpm sieht zunächst wie npm aus, da die CLI-Verwendung ähnlich ist, die Verwaltung von Abhängigkeiten jedoch sehr unterschiedlich ist; die Methode von pnpm sorgt für eine bessere Leistung und optimale Speicherplatzeffizienz. Yarn Classic erfreut sich immer noch großer Beliebtheit, gilt jedoch als veraltete Software und der Support könnte in naher Zukunft eingestellt werden. Yarn Berry PnP ist neu, aber sein Potenzial, die Welt der Paketmanager noch einmal zu revolutionieren, ist noch nicht ausgeschöpft. pnpm 起初看起来像 npm,因为它们的 CLI 用法相似,但管理依赖项却大不相同;pnpm的方法带来更好的性能和最佳的磁盘空间效率。Yarn Classic 仍然很受欢迎,但它被认为是遗留软件,并且在不久的将来可能会放弃支持。Yarn Berry PnP 是全新的,但人们尚未意识到其再次彻底改变包管理器领域的潜力。

多年来,许多用户询问谁使用哪些包管理器,总体而言人们似乎对 Yarn Berry PnP

Im Laufe der Jahre haben viele Benutzer gefragt: Weitere Informationen zu Knoten finden Sie unter: nodejs-Tutorial🎜! 🎜

Das obige ist der detaillierte Inhalt vonJavaScript-Paketmanager im Vergleich: Npm vs. Yarn vs. Pnpm. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:logrocket.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen