大家好! 我相信你已经看到过 使用不同的包管理器,例如: Node.js 项目 (默认) npm 纱 韓國 我自己也见过这种情况,也使用过上述所有方法,但我总是有一个问题 - 是什么驱使人们/团队使用 或 而不是 ? 优点是什么? 有什么缺点吗? yarn pnpm npm 好吧...让我们来一探究竟! 性能比较规则 我决定从“速度”的角度比较一下 、 和 …… npm yarn pnpm 您将看到以下 3 个指标: 生成没有任何缓存的锁文件。 从现有锁文件安装依赖项,无需任何缓存。 使用全局缓存从现有锁文件安装依赖项。 缓存有两种类型: 全球的。 通常存储在用户的主目录(fe, )中。 ~/.yarn/berry/cache 当地的。 存储在项目目录(fe, )。 <project-dir>/.yarn 虽然根据我的经验, 和 是最常见的用例,但为了以防万一,我也选择了 (尽管这是一种非常罕见的情况)。 #2 #3 #1 我使用了 中的示例项目作为基准测试的示例。 create-react-app npm 它是 生态系统的默认包管理器 - 还有什么可说的?它附带安装包,因此当您在计算机上安装 时(或在任何 提供商中,如果您在那里设置了 ),它基本上就可以使用了。 Node.js Node.js CI Node.js 在我看来,这是一个巨大的“优点”——您不需要单独安装它! 没什么特别突出的——它只是……有用!多年来我没有看到任何重大错误——它似乎相当稳定,可以完成工作。 我目前使用过的 的功能: npm 管理依赖项(安装、删除、更新) 发布包(私有、公共) 链接本地包 管理工作区。 管理依赖关系 将依赖项存储在项目根目录的 文件夹中。非常简单。 npm node_modules ℹ️ 存储有关列出的软件包的注册表信息 - 如果你从单一范围获得软件包,它会 方便,即不同注册表中的 (例如 - 和 ): package-lock.json 非常 @example-company npm GitHub Packages 现在,让我们看看它的安装速度如何…… 生成不带任何缓存的 package-lock.json 花了 让 生成 并安装依赖项,而无需任何缓存。 1分钟 npm package-lock.json 使用的命令: npm i 从 package-lock.json 安装依赖项,无需任何缓存 花了 从 安装依赖项而无需任何缓存。 18 秒 npm package-lock.json 使用的命令: npm ci 使用全局缓存从 package-lock.json 安装依赖项 花了 使用全局缓存从 安装依赖项。 8 秒 npm package-lock.json 使用的命令: npm ci 管理工作区 我能够创建 并同时管理整个工作区的依赖关系以及单独管理特定项目的依赖关系。 一个工作区 换句话说 - 它可以毫无错误/问题地完成工作,并且官方文档非常简单明了。 我目前使用过的工作区功能: 为工作区内的所有项目安装依赖项。 为单个特定项目安装依赖项。 一次性递归地为所有项目运行单一脚本。 纱 说实话,我还没有尝试过 的一些功能。我的意思是,我在处理一些项目时经常使用“安装依赖项”功能,仅此而已。 yarn 不附带 安装程序,因此您必须单独安装它。这意味着您的 管道中会有一个额外的步骤 - 您必须在安装项目依赖项之前设置 。 yarn Node.js CI yarn 管理依赖关系 有两种安装依赖项的方法: yarn “ ”(默认) - 创建 文件夹并列出 和 文件中的包。 零安装 .yarn yarn.lock .pnp.cjs 常规的 - 类似于 ,将依赖项存储到 中并将它们列在 文件中。 npm node_modules yarn.lock ℹ️ 当您使用旧的(常规)安装方法时, lock 文件才会存储有关所有列出的包的注册表的信息。 仅 yarn ⚠️请记住,“ ”似乎将包存储在本地缓存中并提供指向锁定文件的链接: 零安装 如果您有一个 或 管道,您可以在一个干净的环境中安装依赖项,然后想要将其移动到另一个环境(您必须复制 文件夹和本地缓存),那么这对您来说可能很重要。 Dockerfile CI .yarn 由于 yarn 现在的默认方法是“ ”,并且比旧方法具有更好的性能 - 我们将仅使用这种方法来记录基准。 零安装 生成不使用任何缓存的锁定文件 花了 为 生成一个 文件并安装依赖项(无缓存)。 16.5 秒 yarn yarn.lock 使用的命令: yarn install 从现有锁定文件安装依赖项而不使用任何缓存 花了 使用 “零安装”方式安装依赖项,并且不包含任何缓存。 11 秒 yarn 的 使用的命令: yarn install --frozen-lockfile 使用全局缓存从现有锁定文件安装依赖项 花了 使用“零安装”方法和全局缓存来安装 依赖项。 8 秒 yarn 使用的命令: yarn install --frozen-lockfile 管理工作区 我能够创建 并同时管理所有项目的依赖关系以及分别管理特定项目的依赖关系。 一个工作区 我目前使用过的工作区功能: 为工作区内的所有项目安装依赖项。 为单个特定项目安装依赖项。 一次性递归地为所有项目运行单一脚本。 文档很好,但是命令名称和标志有点令人困惑。 例如,我必须执行此操作才能在 ( ) 和嵌套的 项目中运行 脚本: 根目录 . b2b test yarn workspaces foreach -A --include '{.,b2b}' run test 与 相比: npm npm run test --workspace=b2b --include-workspace-root 韓國 目前正受到热捧—— 。 pnpm 许多公司和开源项目都在使用它 就像 一样 - 不附带 安装程序,因此您必须单独安装它。这意味着您的 管道中将有一个额外的步骤 - 您必须在安装项目依赖项之前设置 。 yarn pnpm Node.js CI pnpm 管理依赖关系 被认为是 …… pnpm “ ” 快速、节省磁盘空间的包管理器 确实,我同意在本地管理依赖项方面的 说法。 “磁盘空间高效” 默认情况下, 会删除共享依赖项的重复 。pnpm 为多个依赖项中使用的包创建符号链接。例如,如果包 和 使用包 作为依赖项 - 将把包 存储为单个副本并为包 和 创建符号链接。这样,包管理器就不会创建硬拷贝并节省 SSD/HDD 上的内存。 pnpm 项 a b c pnpm c a b ℹ️ 不存储有关列出的包的注册表的信息。 pnpm-lock.yaml ⚠️请记住, 有时会将依赖项存储在全局缓存中,而不是将其保存在项目中。 pnpm 生成无任何缓存的 pnpm-lock.yaml 花了 为 生成 并安装依赖项,无需任何缓存。 31 秒 pnpm pnpm-lock.yaml 使用的命令: pnpm install 从 pnpm-lock.yaml 安装依赖项(不使用全局缓存) 花了 从 安装依赖项(无需缓存)。 16 秒 pnpm pnpm-lock.yaml 使用的命令: pnpm i --frozen-lockfile 使用全局缓存从现有锁定文件安装依赖项 花了 使用全局缓存从 安装依赖项。 5秒 pnpm pnpm-lock.yaml 使用的命令: pnpm i --frozen-lockfile 管理工作区 现在,事情变得非常有趣了…… 有很多配置选项,但一些核心功能根本不起作用! pnpm 让我们回顾一下我遇到的几个错误: pnpm 安装--filter 能够仅为特定项目安装依赖项非常重要——当您在工作区内创建与特定项目相关的管道时,它对于 monorepos 非常有用。 即,想象一下你的工作区中有: 一个网络应用程序, 后端服务器, 测试项目(端到端测试)。 所有这些都是独立的 项目,但它们是同一个 repo 的一部分☝️ npm 现在,您希望管道仅运行端到端测试。因此,您只需要端到端测试依赖项,对吗? 好吧,您将无法做到这一点 - 强制您为整个工作区安装依赖项! pnpm 本来应该仅为选定的项目安装依赖项,但它不起作用。 pnpm install --filter <project-name> 这里有一个一年前的错误,最近它被关闭了,并且没有提供任何有效的修复程序。 递归安装=false 当你运行 时, 默认会为整个工作区(所有项目)安装依赖项 pnpm install pnpm 如果在工作区根目录的 中设置 则可以改变此行为。 .npmrc recursive-install=false 但 。 它引入了另一个已存在近两年的错误 共享工作区锁文件=false 默认将依赖项列表存储在单个锁文件中(与 和 相同)。 pnpm npm yarn 如果您在工作区根目录的 中设置 您也可以改变这种行为。 .npmrc shared-workspace-lockfile=false 这将允许我们保留工作区功能并使用 标志来为特定项目安装依赖项。 --ignore-workspace 无论如何,这种设置会带来更多问题: 和 在我的 管道中抛出 错误。 eslint tsc --noEmit GitHub Actions “JavaScript 堆内存不足” 一些依赖项存储在全局缓存中,并在 中符号链接。 node_modules/.pnpm 性能比较结果 # npm 纱 韓國 生成锁文件 60 秒 16.5 秒 31 秒 不使用任何缓存来安装依赖项 18 秒 11 秒 8 秒 使用全局缓存安装依赖项 8 秒 8 秒 5 秒 根据上述基准测试, 是最慢的包管理器☝️ npm 无论如何,让我们解释一下这些结果…… 生成锁文件 这种情况很少见。通常,锁定文件是在项目初始化时创建的,然后在安装/更新软件包时展开。 考虑到这一点 - 当你选择包管理器时,这似乎并不是一件非常重要的事情。 安装依赖项 大多数情况下,您的项目都会保留一个特定的依赖项列表,并且您很少添加/删除某些内容。 最有可能的是,您会不时地更新软件包的版本 - 这些变化很小,您会重新使用缓存中的其余软件包。 换句话说,常见的用例是——从包注册表中获取新包并从缓存中获取其余包。 (5-8 秒)几乎是 (8-18 秒)的两倍,中间是 (8-11 秒)。 pnpm npm yarn 结论 事实 确实是 包管理器——在当前评论中这一点很清楚! pnpm “快速且节省磁盘”的 工作区功能存在缺陷,其中一些缺陷多年来一直未解决。 pnpm 和 都需要在 CI 管道中进行额外设置,而 不需要。 pnpm yarn npm 则 和 都不会在其锁文件中存储包注册信息,而 则会存储。 pnpm yarn npm 作者的想法 我认为,如果您对包管理器的要求只是“仅安装依赖项”,那么 是最好的选择。 pnpm 尽管 没有附带开箱即用的 安装程序,但可以使用 或 轻松地在 CI 管道中进行设置。 pnpm Node.js corepack 现有操作 我更喜欢 ,因为: npm 它很稳定(尤其是工作空间), 随 提供,不需要在 CI 管道中进行额外设置, Node.js 将包注册表存储在 中,以便您能够从不同的注册表安装具有单一范围的依赖项。 package-lock.json 这些优点比我使用 或 所节省的速度和磁盘空间更重要。 yarn pnpm 你选择包管理器的标准是什么?别害羞,在下面的评论部分告诉我你的想法!👇😊