Home  >  Article  >  Web Front-end  >  JavaScript package managers compared: Npm vs Yarn vs Pnpm

JavaScript package managers compared: Npm vs Yarn vs Pnpm

青灯夜游
青灯夜游forward
2022-08-09 16:22:513074browse

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!

JavaScript package managers compared: Npm vs Yarn vs Pnpm

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:

  • Read and write data
  • Install or update all dependencies in batches
  • Add, update and delete dependencies
  • Run the script
  • Publish the package

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.

  • 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

Therefore,

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).

A brief history of JavaScript package


The earliest released package manager was

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:

  • node_modules Different dependency resolution algorithms for folder structures (nested & flat, node_modules vs. PnP mode)
  • Different dependency hoisting methods (
  • hoisting)
  • locking Different formats (different performance, such as yarn The one I wrote)
  • Different disk storage package file methods (different space efficiency)
  • Multi-package projects (also known as
  • workspaces) Support is different, which affects maintainability and speed of monorepos
  • Different needs for new tools and commands (different needs for extensibility via plugins and community tools)
  • Configurability and flexibility are different
Let's take a deeper look at the history of how these aspects were determined after the rise of

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.

Pioneer npm

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

, custom scripts, public and private packages, and more.

In 2020, GitHub acquired npm, so in principle npm

is now managed by Microsoft. At the time of writing,

the latest major version is v8, released in October 2021.

Innovator Yarn Classic

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
  • cache installation
  • Offline download
  • File locking (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.

More efficientpnpm

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)

JavaScript package managers compared: Npm vs Yarn vs Pnpm

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 (v2, Berry), Reinventing the Wheel with Plug'n'Play

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 .

Installation Workflow


The package manager must first be installed on each developer’s local and CI/CD systems.

npm

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.

Yarn Classic and Yarn Berry

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 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 中指定的所有依赖项的依赖项管理命令。

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

Commonly used commands

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.

##list outdated depsnpm outdatedyarn outdatedyarn upgrade-interactivepnpm outdatedprint info about depsnpm explain ntl alias: whyyarn why ntllike Classic pnpm why ntlinit projectnpm init -y npm init (interactive) alias: --yesyarn init -y yarn init (interactive) alias: --yesyarn initpnpm init -y pnpm init (interactive) alias: --yesprint licenses infoN/A (via third-party package)yarn licenses listN/A (or via N/A (via third-party package)##update package manager versionperform security auditadd deps to package.json without semveruninstall deps and remove from package.jsonuninstall deps w/o update of package.json

配置文件


配置包管理器发生在您的 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
发包 npm publish yarn publish yarn npm publish pnpm publish
list installed deps npm ls alias: list, la, ll yarn list
pnpm list alias: ls
plugin , other plugin)
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

Security


npm

##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 new

npm version uses a cryptographic algorithm to check the integrity of your installed packages. SHA-512.

yarn

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

pnpm Or use checksum to verify the integrity of each installed package before execute its code.

As we mentioned above, both

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.

As we discussed, this is especially important in a

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

Conclusion


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!

Statement:
This article is reproduced at:logrocket.com. If there is any infringement, please contact admin@php.cn delete