前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript 包管理器

JavaScript 包管理器

作者头像
yiyun
发布2023-05-18 14:37:16
9420
发布2023-05-18 14:37:16
举报
文章被收录于专栏:yiyun 的专栏yiyun 的专栏

引言

npm、yarn、pnpm 都是现代化的 JavaScript 包管理器

npm、yarn、pnpm 异同 ?

npm、yarn、pnpm 都是现代化的 JavaScript 包管理器,它们的异同如下:

  1. npm 是最常见的包管理工具之一,也是默认的包管理工具。 Yarn 是由 Facebook 开源的替代 npm 的包管理工具,带来更快的速度、更好的稳定性和更好的安全。
  2. pnpm 是一种聪明的包管理器,它重复使用相同的依赖项,从而节省磁盘空间和下载时间。 pnpm 支持 npm 和 Yarn 的配置文件,可以很容易地从这些工具慢慢过渡过来, 而无需在项目中使用其他的配置文件
  3. 由于 Yarn 和 pnpm 重用相同的依赖,因此它们可以更快地安装依赖项,从而加速构建过程。
  4. npm 和 Yarn都能够通过包锁定功能确保安装的包的版本。 但是,在锁定包版本之后,如果需要在项目中更新某些包,则需要手动更新明确的包版本。
  5. 相较 npm 和 Yarn,pnpm 具有更少的重复代码, 因为它可以与所有项目共享相同的依赖,这对于多项目开发者来说非常优美。

总之,选择哪个包管理工具取决于自己的喜好和项目需求。 如果你喜欢 npm 并且没有太多的依赖,那么使用 npm 可能比较合适。 如果你需要更快的速度和更好的安全,那么使用 Yarn 可能更好。 而如果你需要节省磁盘空间并缩短安装时间,则 pnpm 也是一个很好的选择。

npm、yarn、pnpm 在 node_modules 上管理实现

npm、yarn、pnpm 在管理 node_modules 上的实现方式不同,具体如下:

  1. npm 会在项目中生成 package-lock.json 文件或 npm-shrinkwrap.json 文件, 用于锁定每个包的确切版本。 当安装依赖时,npm 将检查这些文件,以确保相同版本的依赖项在任何地方都得到安装。 npm 在安装依赖时会一次性将所有包下载到本地的 node_modules 目录中, 因此在 node_modules 中会出现很多重复的包。
  2. Yarn 也会生成类似的 yarn.lock 文件用于锁定每个包的确切版本, 与 npm 不同的是,yarn 会尝试重用已经安装好的依赖项, 因此它会在全局缓存中查找包,而不是每次都下载它们。 这样可以节省下载时间和磁盘空间。 同时,Yarn 还会针对性的下载每个包的不同版本并存储在单独的目录中, 以便将其重用于其他项目。
  3. pnpm 使用符号链接来实现 node_modules 的管理。 如果多个项目都使用相同的依赖项,则 pnpm 仅下载一次该依赖项, 并在 node_modules 目录中创建符号链接以便在多个项目之间共享。

总而言之,这些包管理器都使用锁定文件来确保依赖项版本一致性, 并生成一个 node_modules 目录,其中包含所有项目的依赖项。 它们的主要区别在于它们如何确保依赖项和包版本的一致性, 以及如何管理 node_modules 目录中的包。

Q&A

补充

pnpm

  1. 包安装速度极快
  2. 磁盘空间利用效率高

依赖都在 node_modules/.pnpm 下面,别的都是硬链接过去的, 所有实际的文件都在你的 PNPM_HOME 里头

和 npm 不同,pnpm 通过创建符号链接的方式来管理依赖项,而不是像 npm 那样创建本地副本。 当安装依赖项时,pnpm 会在全局安装存储库中缓存所有依赖项的包。 在项目中安装依赖项时,pnpm 会创建一个 node_modules/.pnpm-local 目录的符号链接, 该目录包含一个符号链接的包和符号链接的二进制可执行文件。 依赖项的版本信息保留在 node_modules/.pnpm-store 目录中的元数据文件中。

依赖项的符号链接技术允许多个项目共享相同的依赖项,这样可以节省磁盘空间和下载时间。 相比于 npm 和 Yarn,即使在大型项目中,pnpm 仍然可以很好地管理依赖项,并且能够加快安装速度。 但是,使用符号链接也可能导致某些不兼容问题,因为符号链接可能会在不同操作系统、文件系统或设备中处理不同。

磁盘空间利用效率高

pnpm 的 node_modules 布局使用 符号链接 来创建 依赖项的嵌套结构node_modules 中每个包的每个文件都是来自内容可寻址存储的 硬链接

Q: 为什么说 pnpm 这种 基于内容寻址 的方式对磁盘空间利用效率比较高 ? A: 1. 不会重复安装同一个包。 使用 npm/yarn 的时候,如果100个包依赖 express , 那么就可能安装了100次 express ,磁盘中就有100个地方写入了这部分代码。 但是 pnpm 会只在一个地方写入这部分代码,后面使用会直接使用硬链接 2. 即使一个包的不同版本,pnpm 也会极大程度地复用之前版本的代码。 举个例子,比如 express4.18.1epxress5.0.0-beta.1的两个版本升级对比, epxress5.0.0-beta.1只是重新下载了19个新的更新的包。

pnpm npmyarn 有何不同 ?

npm 2 的依赖管理

npm 2 依赖管理: 会按照安装包的依赖树形结构直接填充在本地的目录结构下

比如 expresskoa 他们会同时依赖 accepts, 那么在 install 之后生成的 node_modules 就会是如下结构:

npm 2 的这种方式的优点就是比较直观,但是缺点也显而易见

  1. 层级依赖过深
  2. 相同包的相同版本会多次被下载,利用率低,占用磁盘空间大

npm3/yarn 的依赖管理

针对 npm2 的两个缺点,npm3 做了更新, 不再使用嵌套的结构,而是将依赖进行展平, 这样就能解决层级依赖深和包的利用率的问题,那么上面的依赖关系就会变成下面这个样子:

在文件里看就是下面的这个样子(为了方便观看,把其他依稀依赖包手动删除了):

可以看到,express@4.18.1koa@2.13.4引用了accepts的版本是一样的, 这样才会被平铺在node_modules下,那如果引用的包的版本不一样又是什么样的情况呢? 就像 debug,http-errorsstatuses 等这几个包

  • express@4.18.1 引入的是: debug@2.6.9http-errors@2.0.0statuses@2.0.1
  • koa@2.13.4 引入的是: debug@4.3.2http-errors@1.6.3statuses@1.5.0

此时,在node_modules结构是下面这个样子:

npm3 的这种平铺方式确实是解决了层级依赖深和包的利用率的问题,但是也引入了其他的问题:

  1. 对没有手动引入的包, 例如 express@4.18.1 依赖的 cookie, 项目中手动引入, 但是依然可以使用, 这样就造成了如果哪天 express 改变了策略不再使用 cookie,而我们的项目中又使用了 cookie, 这样就会导致项目无法启动
  2. 虽然 npm 是共享了相同版本的依赖, 但是如果版本不同,npm还是会完整的下载两个不同的版本,这样也会有依赖的冗余

pnpm 的依赖

pnpm 为了解决 npm3 带来的一些问题, 采用了另外一种方式来管理依赖:pnpm 的 node_modules 布局使用 符号链接 来创建依赖项的 嵌套结构

node_modules 中 .pnpm 下每个包的每个文件都是来自内容可寻址存储的 硬链接

这是 node_modules 中的唯一的 "真实" 物理文件。 一旦所有包都硬链接到 node_modules,就会创建符号链接来构建嵌套的依赖关系图结构。

用 pnpm 安装一下 express@4.18.1koa@2.13.4,生成的目录如下所示:

node_modules 中的依赖只有在 package.json 中手动引入的依赖 expresskoa, 细心的你会发现这两个文件后面有一个箭头, 而这个箭头就是 pnpm 使用的 软连接 的方式指向了 .pnpm 文件真正的文件:

这些文件会在磁盘中统一存储,如果有依赖不同版本的时候,pnpm 也只会下载不同版本中不同的内容。

硬链接和软连接的区别

Linux下有两种链接,一种是硬链接(Hard Link),另一种是符号链接(Symbolic Link),也可以称之为软连接

  • 硬链接:只能引用同一文件系统中的文件。 它引用的是文件在文件系统中的物理索引(inode)。 当移动或者删除原始文件时,硬链接不会被破坏, 因为它所引用的是文件的物理数据而不是文件在文件结构中的位置。 硬链接记录的是目标的 inode。 同一文件的不同硬链接文件相当于该文件的多个不同文件名,即多个不同访问路径,他们的inode都是一样的。 不可以为目录创建硬连接。
  • 符号链接:和原文件不是同一个文件,符号链接会有自己的inode,它所引用的是原文件的 path, 当原文件被移动或删除的时候,符号链接的文件就不可以。 例如 Windows 中的快捷方式。 也可以为目录创建软连接。 如何建立硬链接和软连接呢 可以使用 ln 命令来创建
  • ln 原文件名 硬链接文件名, 例如: ln file hardfile,就是创建了file文件的硬链接文件 hardfile
  • ln -s 原文件名 软链接文件名,例如: ln -s file softfile,就是创建了 file 文件的软链接文件 softfile

在系统中查看操作一遍(执行以下命令)

代码语言:javascript
复制
touch file && echo 'thisi is init file' > file
ln file hardfile
ln -s file softfile 
ln -ls

可以看到 hardfilefile 的inode是一样的(最左侧的33038778),而 softfile 是有了一个自己的inode 此时如果删除 file 文件 rm file,再去查看 hardfilesoftfile 看一下有什么变化

代码语言:javascript
复制
cat hardfile
cat softfile

此时会发现,hardfile 文件是不受影响的,softfile 已经不存在了,因为它链接到的 file 已经不存在了

其他对比

以下是官方给出的 pnpmnpmyarn 的对比

标题

pnpm

yarn

npm

工作空间支持(monorepo)

✔️

✔️

✔️

隔离的 node_modules

✔️ - 默认

✔️

提升的 node_modules

✔️

✔️

✔️ - 默认

自动安装 peers

✔️ - 通过 auto-install-peers=true

✔️

Plug'n'Play

✔️

✔️ - 默认

零安装

✔️

修补依赖项

✔️

管理 Node.js 版本

✔️

有锁文件

✔️ - pnpm-lock.yaml

✔️ - yarn.lock

✔️ - package-lock.json

支持覆盖

✔️

✔️ - 通过 resolutions

✔️

内容可寻址存储

✔️

动态包执行

✔️ - 通过 pnpm dlx

✔️ - 通过 yarn dlx

✔️ - 通过 npx

参考

感谢帮助!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • npm、yarn、pnpm 异同 ?
  • npm、yarn、pnpm 在 node_modules 上管理实现
  • Q&A
  • 补充
    • pnpm
      • 磁盘空间利用效率高
    • pnpm 与 npm、yarn 有何不同 ?
      • npm 2 的依赖管理
      • npm3/yarn 的依赖管理
      • pnpm 的依赖
    • 硬链接和软连接的区别
      • 其他对比
      • 参考
      相关产品与服务
      对象存储
      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档