Home >Web Front-end >JS Tutorial >JavaScript package managers compared: Npm vs Yarn vs Pnpm
This article will take you through the three JavaScript package managers (npm, yarn, pnpm), compare these three package managers, and talk about the differences and relationships between npm, yarn, and pnpm. I hope It is helpful to everyone. If you have any questions, please point them out!
Three major players in the package manager space:
We've actually implemented basically similar functionality in all package managers, so you'll most likely decide which package manager to use based on non-functional requirements, such as installation speed, storage consumption, or practicality.
Of course, the way you choose to use each package manager will be different, but they all have basically the same concept. All of the above package managers can execute the following instructions:
However, despite this, package managers are different under the hood. Traditionally npm
and Yarn
have dependencies installed in a flat node_modules folder. (Pay attention to the order here, yarn
is tiled first, before npm
is recursive). But tiling can also cause a series of safety issues.
Therefore,
Uncertainty of dependency structures.
- The flattening algorithm itself is
complexityvery high and takes a long time.
- The project can still
Illegal access
- Packages with declared dependencies
pnpm introduces some new concepts in the
node_modules folder to store dependencies more efficiently.
Yarn Berry even goes further by completely abandoning the (PnP) mode of
node_modules (another article will explain this in detail).
npm, as early as January 2010. It established the core principles of how package managers work today. But since
npm has been around for over 10 years, why is there any other option? Here are some key reasons why this happens:
Different dependency resolution algorithms for folder structures (nested & flat,
node_modules vs. PnP mode)
)
Different formats (different performance, such as
yarn The one I wrote)
) Support is different, which affects maintainability and speed of
monorepos
npm, and how
Yarn Classic solved them Some questions about how
pnpm extends these concepts, and how
Yarn Berry as the successor to
Yarn Classic breaks these traditional concepts and processes.
npm is the originator of package managers. Many people mistakenly believe that npm is an acronym for "Node package manager", but this is not the case.
Its release constitutes a revolution, because before, project dependencies were downloaded and managed manually.
npm introduces things like files and their metadata fields, storing dependencies in node_modules
In 2020,
GitHub acquired npm, so in principle
npm
the latest major version is v8, released in October 2021.
In October 2016, Facebook announced a partnership with Google and a number of other companies to develop a new package manager (engineering.fb.com /2016/10/11/…) to address the consistency, security, and performance issues that existed with npm at the time. They named the replacement Yarn.
Although Yarn
is still architected and designed based on many concepts and processes of npm
, Yarn
still has a significant impact on the field of package managers. Influence. Yarn
parallelizes operations to speed up the installation process compared to npm
, which has been a major pain point with earlier versions of npm
.
Yarn
set higher standards for reading and writing, security and performance, and invented many concepts (later npm
also made many improvements for this ), including:
monorepo
Support Locking
)Yarn v1 entered maintenance mode in 2020. Since then, the v1.x series has been considered legacy and renamed to Yarn Classic
. Its successor Yarn v2 (Berry) is now the more active development branch.
pnpm
pnpm
1st edition by Zoltan Kochan in 2017 Released in year. It's a replacement for npm
, so if you have a npm
project, you can use pnpm
right away!
The main reason for creating pnpm
is that npm
and Yarn
are very redundant for dependency storage structures used across projects. Although Yarn Classic
has a speed advantage over npm
, it uses the same dependency resolution method, which is not possible with pnpm
: npm
and Yarn Classic
use hoisting
to tiling their node_modules
.
pnpm
without optimizing the previous structure , but introduces another dependency resolution strategy: A storage structure with content addressing. The node_modules
folder generated by this method actually relies on the ~/.pnpm-store/
directory that is globally stored on the main folder. Each version of dependencies is physically stored once in this directory folder, forming a single source address to save considerable disk space. The
node_modules
structure is a nested structure of dependencies created by using symlinks
(where each file/package in the folder is through a hard linkStorage) The following image from the official documentation illustrates this. (To be filled: soft and hard links)
The influence of pnpm can be seen in the 2021 report
: because they are in Innovations in content-addressable storage, competitors are looking to adopt pnpm
concepts, such as the structure of symbolic links and efficient disk management of packages.
Yarn 2 was released in January 2020 and was promoted as the original ## A major upgrade for #Yarn.
Yarn The team called it
Yarn Berry to make it more obvious that it is essentially a new package manager with a new code base and new principles specification.
Yarn Berry
's main innovation is its Plug and Play (PnP) approach, which serves as a strategy for repairing node_modules. Instead of the strategy of generating node_modules
, generate a file .pnp.cjs
with a dependency lookup table, which works since it is a single file rather than a nested folder structure Handle dependencies more efficiently. In addition, each package is stored in a folder as a zip file instead of .yarn/cache/
, and takes up less disk space than node_modules
.
All of these changes happened so quickly that they caused a lot of controversy after they were released. Such breaking breaking changes to PnP require maintainers to update their existing packages to be compatible with them. Using the new PnP approach by default and reverting to node_modules
was not straightforward at first, which led to many high-profile developers not considering it and publicly criticizing Yarn 2.
Since then, the Yarn Berry
team has solved many issues in its subsequent releases. To resolve PnP incompatibility issues, the team has provided a way to easily change the default operating mode. With the help of the node_modules plugin, switching back to the traditional node_modules
method only requires one line of configuration.
Additionally, the JavaScript ecosystem has provided more and more support for PnP over time, and as you can see in this compatibility table, some large Project has started to adopt Yarn Berry
.
Although Yarn Berry
is still young, it has already made an impact on the package manager space - pnpm
adopted the PnP approach in late 2020 .
The package manager must first be installed on each developer’s local and CI/CD systems.
npm
ships with Node.js
, so no additional steps are required. In addition to downloading the Node.js installer for your operating system, it has become a common practice to use CLI tools to manage software versions. In the context of Node, Node Version Manager (nvm) or Volta have become very handy utilities.
You can install Yarn 1 in different ways, for example, as an npm
package To install: .$ npm i -g yarn
To migrate from Yarn Classic to Yarn Berry, the recommended method is:
Install or updateYarn Classic
to the latest version
Use the command to upgrade to the latest modern version
yarn set version berry
However, the recommended method to install Yarn Berry is through Corepack.
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 install alias: i, add | yarn install or yarn | like Classic | pnpm install alias: i |
update deps in package.json acc. semver | npm update alias: up, upgrade | yarn upgrade | yarn semver up (via plugin) | pnpm update alias: up |
update deps in package.json to latest | N/A | yarn upgrade --latest | yarn up | pnpm update --latest alias: -L |
update deps acc. semver | npm update react | yarn upgrade react | yarn semver up react | pnpm up react |
update deps to latest | npm update react@latest | yarn upgrade react --latest | yarn up react | pnpm up -L react |
update deps interactively | N/A | yarn upgrade-interactive | yarn upgrade-interactive (via plugin) | $ pnpm up --interactive alias: -i |
add runtime deps | npm i react | yarn add react | like Classic | pnpm add react |
add dev deps | npm i -D babel alias: --save-dev | yarn add -D babel alias: --dev | like Classic | pnpm add -D babel alias: --save-dev |
add deps to package.json without semver | npm i -E react alias: --save-exact | yarn add -E react alias: --exact | like Classic | pnpm add -E react alias: --save-exact |
uninstall deps and remove from package.json | npm uninstall react alias: remove, rm, r, un, unlink | yarn remove react | like Classic | pnpm remove react alias: rm, un, uninstall |
uninstall deps w/o update of package.json | npm uninstall --no-save | N/A | N/A | N/A |
下面的例子展示了如何在开发期间管理包。表中使用的术语:
- Package: dependency or binary
- Binary: 一种执行工具来自
node_modules/.bin/
或者.yarn/cache/
(PnP)
重要的是要理解,Yarn Berry
只允许我们执行在 package.json
中或者暴露在 bin/
文件中的指定的二进制文件。
Action | npm | Yarn Classic | Yarn Berry | pnpm |
---|---|---|---|---|
install packages globally | npm i -g ntl alias: --global | yarn global add ntl | N/A (global removed) | pnpm add --global ntl |
update packages globally | npm update -g ntl | yarn global upgrade ntl | N/A | pnpm update --global ntl |
remove packages globally | npm uninstall -g ntl | yarn global remove ntl | N/A | pnpm remove --global ntl |
run binaries from terminal | npm exec ntl | yarn ntl | yarn ntl | pnpm ntl |
run binaries from script | ntl | ntl | ntl | ntl |
dynamic package execution | npx ntl | N/A | yarn dlx ntl | pnpm dlx ntl |
add runtime deps | npm i react | yarn add react | like Classic | pnpm add react |
add dev deps | npm i -D babel alias: --save-dev | yarn add -D babel alias: --dev | like Classic | pnpm add -D babel alias: --save-dev |
add deps to package.json without semver | npm i -E react alias: --save-exact | yarn add -E react alias: --exact | like Classic | pnpm add -E react alias: --save-exact |
uninstall deps and remove from package.json | npm uninstall react alias: remove, rm, r, un, unlink | yarn remove react | like Classic | pnpm remove react alias: rm, un, uninstall |
uninstall deps w/o update of package.json | npm uninstall --no-save | N/A | N/A | N/A |
This table covers some useful built-in commands. If there is no official command, third-party commands can usually be used through the npm
package or the Yarn Berry
plugin.
Action | npm | Yarn Classic | Yarn Berry | pnpm | |||
---|---|---|---|---|---|---|---|
发包 | npm publish | yarn publish | yarn npm publish | pnpm publish | |||
list installed deps | npm ls alias: list, la, ll | yarn list | pnpm list alias: ls | ||||
npm outdated | yarn outdated | yarn upgrade-interactive | pnpm outdated | ||||
npm explain ntl alias: why | yarn why ntl | like Classic | pnpm why ntl | ||||
npm init -y npm init (interactive) alias: --yes | yarn init -y yarn init (interactive) alias: --yes | yarn init | pnpm init -y pnpm init (interactive) alias: --yes | ||||
N/A (via third-party package) | yarn licenses list | N/A (or via | plugin , other plugin) | N/A (via third-party package)||||
N/ A (with third-party tools, e.g., nvm) | with npm: yarn policies set-version 1.13.0 | with Corepack: yarn set version 3.1.1 | N/A (with npm, Corepack) | ||||
npm audit | yarn audit | yarn npm audit | pnpm audit | ||||
npm i -E react alias: --save-exact | yarn add -E react alias: --exact | like Classic | pnpm add -E react alias: --save-exact | ||||
npm uninstall react alias: remove, rm, r, un, unlink | yarn remove react | like Classic | pnpm remove react alias: rm, un, uninstall | ||||
npm uninstall --no-save | N/A | N/A | N/A |
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 Is a little too forgiving when it comes to bad packages and encountered some security vulnerabilities that directly affected many projects. For example, in version 5.7.0, when you execute the
sudo npm command on a Linux operating system, you can
change the ownership of system files, rendering the operating system unusable.
Another incident occurred in 2018 involving the theft of Bitcoin. The Node.js package EventStream has a malicious dependency added in its 3.3.6 version. This malicious package contains a cryptographic method that attempts to steal Bitcoins from the developer's machine.
To help resolve these issues, the newnpm version uses a
cryptographic algorithm to check the integrity of your installed packages. SHA-512.
Yarn Classic and
Yarn Berry use
checksum from the start to verify the integrity of each package. Yarn also attempts to prevent you from retrieving malicious packages that are not declared in
package.json: if a mismatch is found, the installation is aborted.
Yarn Berry in PnP mode does not have the security issues of the traditional
node_modules way. Compared with
Yarn Classic,
Yarn Berry improves the security of command execution. You can only execute packages that have been declared in
package.json. This security feature is similar to
pnpm, which I describe below.
pnpm Or
use checksum to verify the integrity of each installed package before execute its code.
npm and
Yarn Classic have
security issues due to promotion. pnpm avoids this situation because its management model does not use elevation; instead, it generates nested
node_modules folders, thus eliminating the risk of illegal dependency access. This means that dependencies are declared in
.package.json.
monorepo setting, since boosting algorithms can sometimes lead to
nondeterministic dependencies.
npm | Yarn Classic | Yarn Berry | pnpm |
Svelte | React | Jest (with node_modules) | Vue 3 |
Preact | Angular | Storybook (with node_modules) | Browserlist |
Express.js | Ember | Babel (with node_modules) | Prisma |
Meteor | Next.js | Redux Toolkit (with node_modules) | SvelteKit |
Apollo Server | Gatsby | ||
Nuxt | |||
Create React App | |||
webpack-cli | |||
Emotion |
There are indeed big differences in the principles of different package managers.
pnpm
looks like npm
at first, as their CLI usage is similar, but managing dependencies is very different; pnpm
's approach Bringing better performance and optimal disk space efficiency. Yarn Classic
is still popular, but it is considered legacy software and support may be dropped in the near future. Yarn Berry PnP
is brand new, but its potential to revolutionize the package manager landscape yet again is not yet realized.
Over the years many users have asked who uses which package managers, and overall people seem to be particularly interested in the maturity and adoption of Yarn Berry PnP
.
The purpose of this article is to provide you with multiple perspectives to decide which package manager to use for yourself. I'd like to point out that I don't recommend a specific package manager. It depends on how you weigh the different requirements - so you can still choose whatever you like!
English original address: https://blog.logrocket.com/javascript-package-managers-compared/
For more node-related knowledge, please visit:nodejs tutorial!
The above is the detailed content of JavaScript package managers compared: Npm vs Yarn vs Pnpm. For more information, please follow other related articles on the PHP Chinese website!