이 기사에서는 세 가지 JavaScript 패키지 관리자(npm, Yarn, pnpm)를 소개하고 이 세 가지 패키지 관리자를 비교하며 npm, Yarn 및 pnpm 간의 차이점과 관계에 대해 설명합니다. 모든 사람에게 도움이 되기를 바랍니다. 도움이 됩니다. 궁금한 점이 있으면 지적해 주세요!
패키지 관리자 분야의 세 가지 주요 플레이어:
사실 우리는 기본적으로 비슷해요 기능은 모든 패키지 관리자에서 구현되므로 설치 속도, 저장소 소비 또는 실용성과 같은 비기능적 요구 사항에 따라 사용할 패키지 관리자를 결정할 가능성이 높습니다.
물론 각 패키지 관리자를 사용하는 방법은 다르지만 기본적으로는 모두 동일한 개념을 가지고 있습니다. 위의 모든 패키지 관리자는 다음 명령을 실행할 수 있습니다.
그러나 그럼에도 불구하고 이 패키지 관리자는 내부적으로 다릅니다. 전통적으로 npm
및 Yarn
은 타일식 node_modules 폴더 npm
和 Yarn
将依赖项安装在一个平铺的node_modules文件夹中。(这里注意先后顺序,是 yarn
先平铺的,之前 npm
是递归)。但是平铺也会造成一系列的安全问题。
依赖结构的不确定性。
扁平化算法本身的复杂性很高,耗时较长。
项目中仍然可以非法访问
有声明过依赖的包
因此,pnpm
在 node_modules
文件夹中引入了一些新概念来更高效的存储依赖,。Yarn Berry
甚至通过完全放弃 node_modules
的 (PnP) 模式(另一个文章会具体说明)来走得更远。
最早发布的包管理器是 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
是“Node package manager”的首字母缩写词,但事实并非如此。
它的发布构成了一场革命,因为在此之前,项目依赖项都是手动下载和管理的。npm
引入了诸如文件及其元数据字段、将依赖项存储在node_modules
, 自定义脚本, 公共和私有包等等。
2020 年,GitHub 收购了 npm,所以原则上 npm
. (여기서 순서에 주의하세요. npm
이 재귀적이기 전에 yarn
이 먼저 타일링됩니다.) 그러나 타일링은 일련의 안전 문제를 일으킬 수도 있습니다.
pnpm
은 node_modules 종속성을 보다 효율적으로 저장하기 위해
폴더에 몇 가지 새로운 개념이 도입되었습니다. Yarn Berry
는 더 나아가 node_modules
의 (PnP) 모드를 완전히 포기합니다(자세한 내용은 다른 문서 참조). 🎜npm
이었습니다. 2010년 1월 초. 이는 오늘날 패키지 관리자가 작동하는 방식에 대한 핵심 원칙을 확립했습니다. 그런데 npm
이 나온 지 10년이 넘었는데 왜 대안이 있을까요? 이러한 일이 발생하는 몇 가지 주요 이유는 다음과 같습니다.node_modules
폴더 구조에 대한 다양한 종속성 해결 알고리즘(중첩 및 단순, node_modules
및 PnP 모드)🎜 🎜다른 종속성 끌어올리기 방법(hoisting
)🎜🎜locking
은 형식이 다릅니다(성능이 다르며, 예를 들어 yarn
이 직접 작성한 것임) 🎜🎜 디스크에 패키지 파일을 저장하는 다양한 방법(다양한 공간 효율성) 🎜🎜다중 패키지 프로젝트(작업공간
라고도 함)에 대한 지원이 다르므로 monorepos
에 영향을 미칩니다. 유지 관리 가능성 및 속도 🎜🎜 새로운 도구 및 명령에 대한 다양한 요구 사항(플러그인 및 커뮤니티 도구를 통한 확장성에 대한 다양한 요구 사항) 🎜🎜 다양한 구성 가능성 및 유연성 🎜🎜🎜 npm의 등장 이후에 결정된 사항, <code>Yarn Classic
이 이러한 문제 중 일부를 어떻게 해결했는지, pnpm
이 이러한 개념을 어떻게 확장했는지, 그리고 Yarn Berry
> 어떻게 Yarn Classic
의 후속 제품은 이러한 전통적인 개념과 프로세스를 깨뜨립니다. 🎜npm
은 패키지 관리자의 창시자입니다. 많은 사람들이 npm
이 "노드 패키지 관리자"의 약어라고 잘못 믿고 있지만 사실이 아닙니다 🎜. 🎜🎜 이전에는 프로젝트 종속성을 수동으로 다운로드하고 관리했기 때문에 이 릴리스는 혁명입니다. npm
은 파일 및 해당 메타데이터 필드, node_modules
에 종속성 저장, 사용자 정의 스크립트, 공개 및 비공개 패키지 등을 소개합니다. 🎜🎜2020년에는 GitHub가 npm을 인수했습니다🎜 이므로 원칙적으로 npm
은 이제 Microsoft에서 관리합니다. 이 글을 쓰는 시점에서 🎜최신 메이저 버전은 2021년 10월에 출시된 v8🎜입니다. 🎜2016년 10월 Facebook은 일관성, 보안 문제를 해결하기 위해 Google 및 기타 몇몇 회사와 협력하여 새로운 패키지 관리자(engineering.fb.com/2016/10/11/…)를 발표했습니다. , 당시 npm에 존재했던 성능 문제 등이 있습니다. 그들은 대체품의 이름을 Yarn이라고 명명했습니다.
Yarn
은 여전히 npm
의 여러 개념과 프로세스를 기반으로 설계되고 설계되었지만 Yarn
은 패키지 분야에 큰 영향을 미쳤습니다. 관리자. npm
과 비교하여 Yarn
은 작업을 병렬화하여 설치 프로세스 속도를 높입니다. 이는 npm
이전 버전의 주요 문제점이었습니다. 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
的主要原因是 npm
和 Yarn
对于跨项目使用的依赖项存储结构非常冗余。尽管 Yarn Classic
比 npm
具有速度优势,但它使用相同的依赖解析方法,这对 pnpm
来说是不行的:npm
和 Yarn Classic
使用 hoisting
来平铺他们的 node_modules
.
pnpm
没有优化之前的结构,而是引入了另一种依赖解决策略:内容寻址的一种存储结构。此方法生成的 node_modules
文件夹其实是依赖于全局存储在主文件夹上的 ~/.pnpm-store/
目录。每个版本的依赖项都物理形式存储在该目录文件夹中一次,构成单一的源地址来节省相当多的磁盘空间。
node_modules
结构是通过使用 symlinks
创建依赖关系的嵌套结构(其中文件夹内每个文件/包都是通过硬链接存储)官方文档中的下图阐明了这一点。(待填坑:软硬链接)
2021 年报告中可见 pnpm
的影响力:因为他们在内容可寻址存储方面的创新,竞争对手都希望采用 pnpm
的概念,比如象征性链接的结构和包的高效磁盘管理。
Yarn 2于 2020 年 1 月发布,被宣传为原始 Yarn
的重大升级。Yarn
团队将其称为 Yarn Berry
Yarn
은 읽기 및 쓰기, 보안 및 성능에 대한 더 높은 표준을 설정하고 많은 개념을 창안했습니다(나중에 npm
도 이를 위해 많은 개선을 이루었습니다). 포함: 🎜monorepo
는 잠금
)을 지원합니다. Yarn Classic
으로 이름이 변경되었습니다. 그 후속 제품인 Yarn v2(Berry)는 이제 더욱 활발한 개발 브랜치입니다. 🎜pnpm
🎜🎜🎜Zoltan의 pnpm
버전 1 Kochan🎜은 2017년에 출시되었습니다. npm
을 대체하므로 npm
프로젝트가 있는 경우 pnpm
을 바로 사용할 수 있습니다! 🎜🎜pnpm
을 만드는 주된 이유는 npm
과 Yarn
이 프로젝트 전체에서 사용되는 종속성 저장소 구조에 매우 중복되기 때문입니다. Yarn Classic
은 npm
에 비해 속도 이점이 있지만 pnpm
에서는 불가능한 동일한 종속성 해결 방법을 사용합니다. npm
및 Yarn Classic
은 호이스팅
을 사용하여 node_modules
를 타일링합니다.🎜🎜pnpm
은 이전을 최적화하지 않습니다. 대신 다른 종속성 해결 전략을 도입합니다. A Storage 콘텐츠 주소 지정 구조 🎜. 이 방법으로 생성된 node_modules
폴더는 실제로 기본 폴더에 전역적으로 저장되는 ~/.pnpm-store/
디렉터리에 의존합니다. 각 종속성 버전은 이 디렉터리 폴더에 물리적으로 한 번 저장되어 단일 소스 주소를 형성하여 상당한 디스크 공간을 절약합니다. 🎜🎜node_modules
구조는 symlinks
를 사용하여 생성된 종속성의 중첩 구조입니다(폴더의 각 파일/패키지는 하드 링크 🎜 저장소) 공식 문서의 다음 이미지는 이를 보여줍니다. (채워야 할 항목: 소프트 및 하드 링크) 🎜🎜🎜🎜2021 보고서🎜 pnpm
의 영향은 콘텐츠 주소 지정 가능 스토리지의 혁신🎜, 경쟁업체는 심볼릭 링크의 구조 🎜 및 패키지의 효율적인 디스크 관리. 🎜Yarn
에 대한 주요 업그레이드로 승격되었습니다. Yarn
팀은 이를 Yarn Berry
라고 명명하여 이것이 본질적으로 새로운 코드 기반과 새로운 원칙을 갖춘 새로운 패키지 관리자라는 점을 더욱 분명하게 했습니다. 🎜Yarn Berry
의 주요 혁신은 입니다. 플러그 앤 플레이(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
与 Node.js
一起提供,因此不需要额外的步骤。除了为您的操作系统下载Node.js 安装程序外,使用 CLI 工具管理软件版本已成为一种常见做法。在 Node 的上下文中,Node Version Manager (nvm) 或 Volta 已成为非常方便的实用程序。
您可以通过不同的方式安装 Yarn 1,例如,作为 npm
包来安装:.$ npm i -g yarn
要从Yarn Classic 迁移到 Yarn Berry,推荐的方法是:
安装或更新 Yarn Classic
방법은 Fixing node_modules
node_modules
를 생성하는 전략 대신 종속성 조회 테이블이 있는 .pnp.cjs
파일을 생성하십시오. 이는 중첩된 폴더 구조가 아닌 단일 파일이므로 종속성이 있습니다. 보다 효율적으로 처리할 수 있습니다. 또한 각 패키지는 zip 파일
.yarn/cache/
대신 폴더에 저장되며 node_modules
보다 디스크 공간을 적게 차지합니다. . 이 모든 변화는 너무 빨리 일어나서 출시 후 많은 논란을 불러일으켰습니다. PnP 이 획기적인 변경 사항유지관리자에게 기존 패키지를 업데이트하여
호환되도록 요청하세요. 기본적으로 새로운 PnP 접근 방식을 사용하고node_modules
로 되돌리는 것이 처음에는 쉽지 않았기 때문에 많은 유명 개발자가 참여를 고려하지 않았고 Yarn 2를 공개적으로 비판
이후 Yarn Berry
팀은 많은 문제가 해결되었습니다. PnP 비호환 문제를 해결하기 위해 팀에서는 기본 작동 모드를 쉽게 변경할 수 있는 방법을 제공했습니다. node_modules 플러그인 의 도움으로 기존 방식으로 다시 전환하세요. node_modules
메서드에는 한 줄의 구성만 필요합니다.
Yarn Berry
를 채택하기 시작했습니다. 🎜🎜Yarn Berry
는 아직 초기 단계이지만 이미 패키지 관리자 공간에 영향을 미쳤습니다. pnpm
은 PnP 방법 🎜. 🎜npm
과 Node.js
제공되므로 추가 단계가 필요하지 않습니다. 운영 체제에 맞는 Node.js 설치 프로그램 🎜을 다운로드하는 것 외에도 CLI를 사용하세요. 소프트웨어 버전을 관리하는 도구는 일반적인 관행이 되었습니다. Node의 맥락에서 Node Version Manager(nvm)🎜 또는 Volta🎜는 매우 편리한 유틸리티가 되었습니다. 🎜npm
패키지: .$). npm i -g Yarn
🎜🎜Yarn Classic으로 마이그레이션하려면 Yarn Berry🎜에 권장되는 방법은 다음과 같습니다. 🎜Yarn Classic
을 최신 버전으로 설치 또는 업데이트🎜🎜🎜🎜명령을 사용하여 최신 최신 버전으로 업그레이드하세요🎜yarn set version berry
Corepack是由 Yarn Berry 的开发者创建的。该计划最初被命名为包管理器管理器(pmm) ?,并在 LTS v16 中与 Node 合并。
在 Corepack 的帮助下,因为 Node 包含 Yarn Classic
、Yarn Berry
和 pnpm
二进制文件所以您不必“单独”安装的 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
作为 npm
包来安装: $ npm i -g pnpm
。您还可以使用 Corepack 安装 pnpm :
$ corepack prepare pnpm@6.24.2 --activate
在本节中,您将一目了然地看到不同包管理器的主要特征。您可以轻松发现配置特定包管理器涉及哪些文件,以及哪些文件是由安装步骤生成的。
所有包管理器都将所有重要的元信息存储在项目清单package.json文件中。 此外,根级别的配置文件可以被用来设置不同的私有包或者不同的依赖项解析配置。
在安装步骤中,依赖项 dependencies
被存储在文件结构中,例如 node_modules
并生成锁定文件 locking
。本节不考虑工作区设置,因此所有示例仅显示存储依赖项的单个位置。
使用$ npm install
或较短的 $ npm i
会生成一个 package-lock.json
文件和一个 node_modules
文件夹。还有 .npmrc
这种可配置的文件可以放在根级别目录里面。有关 locking
文件的更多信息,请参阅下一节。
. ├── node_modules/ ├── .npmrc ├── package-lock.json └── package.json
运行 $ 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
项目中处理更多的文件和文件夹。有些是可选的,有些是强制性的。
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
无论是对于PnP 的严格模式还是松散模式,跟着 .pnp.cjs
和 yarn.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`
和 npm
或 Yarn 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
文件夹结构中。这是 npm
、Yarn Classic 和 pnpm都使用的方案,(其中 pnpm
比其他方案更有效)。
Yarn Berry
在 PnP 模式下的做法有所不同。依赖项不是 node_modules
文件夹,而是以 zip 文件的形式存储为 .yarn/cache/
和 .pnp.cjs
文件的组合。
最好将这些锁定文件置于版本控制之下,因为每个团队成员都安装相同的版本,所以它解决了“在你和我的机器上工作”问题。
下表比较了 npm
、Yarn Classic
、Yarn Berry
和 pnpm
中可用的不同 CLI 命令。这绝不是一个完整的列表,而是一个备忘单。本节不涉及与workflow 相关的命令。
npm
和 pnpm
具有许多特别的命令和选项别名,这意味着命令可以有不同的名称,即$ npm install
与 $ npm add
。 此外,许多命令选项都有缩写版本,例如 -D
来代替 --save-dev
。
在表格中,我将所有缩写版本称为别名。使用这些包管理器,您都可以增加、更新或删除多个依赖项。
此表涵盖了用于安装或更新 package.json
中指定的所有依赖项的依赖项管理命令。
Action | npm | Yarn Classic | Yarn Berry | pnpm |
---|---|---|---|---|
install deps in package.json | npm 설치 별칭: i, add | yarn install 아니면 클래식처럼 실 | pnpm 설치 별칭: i | |
package.json acc의 deps를 업데이트합니다. semver | npm 업데이트 별칭: up, 업그레이드 | yarn 업그레이드 | yarn semver up(plugin을 통해) | pnpm 업데이트 별칭: up |
package.json의 deps를 최신 | N/A | 로 업데이트yarn 업그레이드 --latest | yarn up | pnpm update --latest 별칭: -L |
update deps acc. semver | npm 업데이트 반응 | yarn 업그레이드 반응 | yarn semver up 반응 | pnpm up 반응 |
update deps to 최신 | npm 업데이트 React@latest | yarn 업그레이드 반응 --latest | yarn up 반응 | pnpm up -L 반응 |
대화식으로 deps 업데이트 | N/A | yarn 업그레이드-인터랙티브 | yarn 업그레이드-인터랙티브(plugin을 통해) | $ pnpm up --interactive 별칭: -i | ㅋㅋㅋ -D babel 별칭: --dev
pnpm add -D babel 별칭: --save-dev | semver | npm 없이 package.json에 deps를 추가합니다. i -E 반응 별칭: --save -exact | yarn 추가 -E 반응 별칭: --exact | |
pnpm 추가 -E 반응 별칭: --save-exact | deps를 제거하고 package.json에서 제거 | npm 제거 반응 별칭 : 제거, rm, r, un, unlink | yarn 제거 반응 | |
pnpm 제거 반응 별칭: rm, un, uninstall | uninstall deps w/o update of package.json | npm uninstall - -no-save | N/A | |
N/A | 안전관리 | |||
패키지: 종속성 또는 바이너리 | 바이너리: 一种执行工具来自 node_modules/.bin/ 或者 .yarn/cache/ (PnP) | 重要的是要理解,Yarn Berry 只允许我们执行 여기 package.json 中或者暴露에서 bin/ 文件中的指 마음에 드는 2대 -g ntl 별칭: --global |
yarn 전역 추가 ntl |
npm update -g ntl
- yarn 전역 업그레이드 ntl
node_modules/.bin/
或者.yarn/cache/
(PnP)
重要的是要理解,Yarn Berry
只允许我们执行在 package.json
中或者暴露在 bin/
N/A
전 세계적으로 패키지 제거 | npm uninstall -g ntl | yarn global 제거 ntl | N/A | pnpm 제거 --global ntl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
npm exec ntl | yarn ntl | yarn ntl | pnpm ntl | 스크립트에서 바이너리 실행 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ntl | ntl | ntl | 동적 패키지 실행 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
N/A | yarn dlx ntl | pnpm dlx ntl | 런타임 deps 추가 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yarn add React | like Classic | pnpm add React | add dev deps | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yarn add -D babel 별칭: --dev | like Classic | pnpm add -D babel 별칭: --save-dev | semver 없이 package.json에 deps를 추가 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yarn 추가 -E 반응 별칭: --exact | like Classic | pnpm 추가 -E 반응 별칭: --save-exact | deps 제거 및 제거 package.json에서 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yarn 제거 반응 | like Classic | pnpm 제거 반응 별칭: rm, un, uninstall | deps w/o 제거 package.json 업데이트 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
N/A | N/A | N/A |
Action | npm | Yarn Classic | Yarn Berry | pnpm |
---|---|---|---|---|
Publish | npmPublish | yarnPublish | yarn npm 게시 | pnpm 게시 |
목록 설치됨 deps | npm ls 별칭: list, la, ll | yarn list | pnpm 목록 별칭: ls | |
list old deps | npm outdated | yarn outdated | yarn 업그레이드-인터랙티브 | pnpm 오래된 |
deps | npm에 대한 정보 인쇄 ntl 별칭 설명: 왜 | yarn 왜 ntl | like Classic | pnpm 왜 ntl |
init 프로젝트 | npm init -y npm init(대화형) 별칭 s : --yes | yarn init -y Yarn init(대화형) 별칭: --yes | yarn init | pnpm init -y pnpm init(대화형) 별칭: --yes |
라이센스 인쇄 정보 | N / A(타사 패키지를 통해) | 실 라이센스 목록 | N/A(또는 plugin, 기타 plugin을 통해) | N/A(타사 패키지를 통해) |
업데이트 패키지 관리자 버전 | N/A(타사 도구 포함, 예: nvm) | npm 포함: 원사 정책 세트 버전 1.13.0 | Corepack 포함: 원사 세트 버전 3.1.1 | N/A(npm 포함, Corepack ) |
보안 감사 수행 | npm audit | yarn audit | yarn npm audit | pnpm audit |
semver 없이 package.json에 deps 추가 | npm i -E 반응 별칭: --save - 정확한 | yarn 추가 -E 반응 별칭: --exact | like Classic | pnpm 추가 -E 반응 별칭: --save-exact |
deps를 제거하고 package.json에서 제거 | npm 제거 반응 별칭 : 제거, rm, r, un, unlink | yarn 제거 반응 | like Classic | pnpm 제거 반응 별칭: rm, un, uninstall |
uninstall deps w/o update of package.json | npm uninstall - - 저장 안 함 | N/A | N/A | N/A |
配置包管理器发生在您的 package.json
和专用的配置文件中。
monorepo
中的工作区大多数配置发生在专用配置文件 .npmrc
中。
如果你想使用 npm
的 workspaces
功能,你必须在 package.json
中添加workspaces 元数据字段来告诉 npm 在哪里可以找到子项目或工作空间的文件夹。
// ... "workspaces": [ "hooks", "utils" ] }
每个包管理器都可以使用公共 npm
注册表。或许你很可能希望重用它们而不将它们发布到公共注册表。您可以在 .npmrc
文件中执行此操作配置来私有注册表。( 现在基本都有私有源了)
# .npmrc @doppelmutzi:registry=https://gitlab.doppelmutzi.com/api/v4/projects/41/packages/npm/
npm
存在许多配置选项,最好在文档中查看它们。\
您可以在 package.json
中设置 yarn
的 workspaces
(必须是私有包)。
{ // ... "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
中配置 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
使用与 npm
相同的配置机制,因此您可以使用 .npmrc
文件。配置私有注册表的工作方式也与使用 npm
相同。借助 pnpm 的工作空间功能可以支持多包项目。要初始化 monorepo
,您必须在 pnpm-workspace.yaml
文件中指定包的位置。
# pnpm-workspace.yaml packages: - 'packages/**'
(这里其实就是三种概念,单仓库多项目,单仓库单项目,多仓库多项目)
monorepo
是一个包含多个项目的存储库,这些项目被称为 workspace
或者包。将所有内容保存在一个地方而不是使用多个存储库是一种项目组织策略。
当然,这会带来额外的复杂性。Yarn Classic
是第一个启用此功能的,但现在每个主要的包管理器都提供了工作区功能。本节展示如何使用每个不同的包管理器配置工作区。
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 目前不支持高级过滤或并行执行多个与工作区相关的命令。
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 Classic
的概念之上的。在Reddit 评论中,Yarn Berry 的主要开发人员简要概述了面向工作空间的功能,包括:
Yarn Berry
使用大量可用于 package.json
文件的 dependencies
或 devDependencies
字段的协议。其中就有 workspace
协议。
与 Yarn Classic
的工作区相比,Yarn Berry
明确定义依赖项必须是此 monorepo
中的包之一。否则如果版本不匹配,Yarn Berry
可能会尝试从远程注册表获取其版本。
{ // ... "dependencies": { "@doppelmutzi/hooks": "workspace:*", "http-server": "14.0.0", // ... } }
通过 workspace
这种协议,pnpm
促成了类似于 Yarn Berry
的 monorepo
项目。许多 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/`
性能是选型决策的关键部分。本节展示了基于一个小型和一个中型项目的基准测试。以下是有关示例项目的一些说明:
我用三个用例 (UC) 对我们的每个包管理器变体进行了一次测量。要了解详细的评估和解释,请查看项目 1 (P1)和项目 2 (P2)的结果。
node_modules
或 .pnp.cjs
node_modules
或 .pnp.cjs
node_modules
或 .pnp.cjs
我使用工具gnomon来测量安装消耗的时间( yarn
| gnomon
)。此外我测量了生成文件的大小 $ du -sh node_modules
。
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 |
npm
은 잘못된 패키지를 처리할 때 너무 관대하며 많은 프로젝트에 직접적인 영향을 미치는 몇 가지 보안 취약점에 직면했습니다. 예를 들어 버전 5.7.0에서는 Linux 운영 체제에서 sudo npm
명령을 실행하면 시스템 파일의 소유권을 변경npm
在处理坏包时有点过于宽容并且遇到了一些直接影响许多项目的安全漏洞。例如,在 5.7.0 版本中,当您在 Linux 操作系统上执行 sudo npm
命令时,可以更改系统文件的所有权,从而导致操作系统无法使用。
另一起事件发生在 2018 年,涉及比特币被盗。 Node.js 包EventStream在其 3.3.6 版本中添加了恶意依赖项。这个恶意包包含一个加密方法试图从开发者的机器上窃取比特币。
为了帮助解决这些问题,新的 npm
版本使用密码算法来检查您安装的软件包的完整性。SHA-512。
Yarn Classic
和 Yarn Berry
从一开始就使用校验和来检验每一个包的完整性。Yarn
还试图阻止您检索在 package.json
中未声明的恶意包:如果发现不匹配,则中止安装。
PnP 模式下的 Yarn Berry
没有传统 node_modules
方式的安全问题。与 Yarn Classic
相比,Yarn Berry
提高了命令执行的安全性。您只能执行已在 package.json
声明的包。此安全功能类似于 pnpm
,我将在下面进行描述。
pnpm
还是使用校验和来验证每个已安装包的完整性,然后再执行其代码。
正如我们在上面提到的,npm
和 Yarn Classic
都存在由于提升而导致的安全问题。pnpm
避免了这种情况,因为它的管理模型不使用提升;相反,它会生成嵌套 node_modules
文件夹,从而消除非法依赖访问的风险。这意味着依赖关系都在 .package.json
中声明了。
正如我们所讨论的,这在 monorepo
하여 운영 체제를 사용할 수 없게 만듭니다. 또 다른 사건 사건
npm
버전에서는 CryptoAlgorithm 🎜을 사용하여 설치된 패키지의 무결성을 확인하세요. SHA-512🎜. 🎜Yarn Classic
및 Yarn Berry
는 처음부터 사용됩니다. 체크섬🎜을 통해 각 패키지의 무결성을 확인합니다. Yarn
은 또한 package.json
에 선언되지 않은 악성 패키지를 검색하지 못하도록 시도합니다. 불일치가 발견되면 설치가 중단됩니다. 🎜🎜PnP 모드 Yarn Berry
에는 기존 node_modules
접근 방식의 보안 문제가 없습니다. Yarn Classic
과 비교하여 Yarn Berry
는 명령 실행 보안을 향상시킵니다. package.json
에 선언된 패키지만 실행할 수 있습니다. 이 보안 기능은 아래에서 설명하는 pnpm
과 유사합니다. 🎜pnpm
또는 체크섬 🎜을 사용하여 코드를 실행하기 전에 설치된 각 패키지의 무결성을 확인하세요. 🎜🎜위에서 언급했듯이 npm
과 Yarn Classic
이 모두 존재합니다 프로모션 보안 문제로 인해 발생 🎜. pnpm
은 관리 모델이 승격을 사용하지 않고 중첩된 node_modules
폴더를 생성하여 불법 종속성 액세스의 위험을 제거하므로 이러한 상황을 방지합니다. 이는 종속성이 .package.json
에 선언되었음을 의미합니다. 🎜🎜우리가 논의한 것처럼 이는 monorepo
설정에서 특히 중요합니다. 알고리즘을 부스팅하면 때때로 🎜종속적 비결정론🎜으로 이어질 수 있기 때문입니다. 🎜npm | Yarn Classic | 얀베리 | pnpm |
Svelte | React | Jest(node_modules 포함) | Vue 3 |
Preact | Angular | Storybook(node_modules 포함) | Browserlist |
Express .js | Ember | Babel(node_modules 포함) | Prisma |
Meteor | Next.js | Redux 툴킷(node_modules 포함) | SvelteKit |
Apollo 서버 | Gatsby | ||
Nuxt | |||
React 앱 만들기 | |
||
webpack-cli | |||
Emotion |
패키지 관리자마다 원칙에는 실제로 큰 차이가 있습니다.
pnpm
은 CLI 사용법이 비슷하기 때문에 처음에는 npm
처럼 보이지만 종속성을 관리하는 방법은 더 나은 성능을 가져옵니다. 최적의 디스크 공간 효율성을 제공합니다. Yarn Classic
은 여전히 인기가 있지만 레거시 소프트웨어로 간주되어 가까운 시일 내에 지원이 중단될 수 있습니다. Yarn Berry PnP
는 새로운 것이지만 패키지 관리자 세계에 다시 한 번 혁명을 일으킬 수 있는 잠재력은 아직 실현되지 않았습니다. pnpm
起初看起来像 npm
,因为它们的 CLI 用法相似,但管理依赖项却大不相同;pnpm
的方法带来更好的性能和最佳的磁盘空间效率。Yarn Classic
仍然很受欢迎,但它被认为是遗留软件,并且在不久的将来可能会放弃支持。Yarn Berry PnP
是全新的,但人们尚未意识到其再次彻底改变包管理器领域的潜力。
多年来,许多用户询问谁使用哪些包管理器,总体而言人们似乎对 Yarn Berry PnP
, 그리고 전반적인 사람들은 Yarn Berry PnP
의 성숙도와 채택에 특히 관심이 있는 것 같습니다.
이 기사의 목적은 어떤 패키지 관리자를 직접 사용할지 결정할 수 있는 다양한 관점을 제공하는 것입니다. 특정 패키지 관리자를 권장하지 않는다는 점을 지적하고 싶습니다. 다양한 요구 사항을 어떻게 평가하느냐에 따라 다르므로 원하는 것을 선택할 수 있습니다!영어 원본 주소: https://blog.logrocket.com/javascript-package-managers-compared/nodejs tutorial🎜을 방문하세요! 🎜
위 내용은 JavaScript 패키지 관리자 비교: Npm vs Yarn vs Pnpm의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!