【环球速看料】关于包管理器Npm、Yarn和Pnpm的一些总结
2023-04-12 09:28:55    前端一码平川
写在前面

在Node.js生态系统中,包管理器是至关重要的组件之一,它们负责维护各种应用程序和库之间的依赖关系。npm是Node.js的默认包管理器,它的初始版本是npm1,但是它很快就被npm2所取代。


【资料图】

npm2

关于npm2最初作为包管理管理,采用的是node_modules嵌套模式,即每个包都会有自己独立的node_modules,且会将各自依赖进行安装,依赖的依赖也会产生自己的node_modules,这样就产生了“嵌套依赖”。

就像回调嵌套一样,容易陷入回调地狱,嵌套依赖也不例外。

这种嵌套依赖的模式,虽然可以使依赖项的版本更加明确和稳定,但是在实际应用中也存在一些问题。其中最大的问题是包的嵌套层级很深,这可能会导致安装和更新依赖项的时间变长,并增加包的大小。此外,由于每个包都有自己的node_modules文件夹,这可能会导致文件系统中出现大量重复的依赖项,从而占用更多的磁盘空间。

在实际操作中,当需要在特定的Node.js版本中使用npm2时,可以使用Node Version Manager (nvm)来管理多个Node.js版本。例如,在切换到Node.js v4.0版本时,对应的npm版本是npm2.x。

为了更好地说明嵌套依赖的问题,我们可以通过安装koa来演示。koa是一个基于Node.js的Web应用程序框架,它有许多依赖项,我们可以使用以下命令来安装koa:

npm install koa

在安装koa时,npm会自动下载和安装所有必需的依赖项,并将它们安装到koa的node_modules文件夹中。如果我们检查koa的node_modules文件夹,我们会发现它包含了大量的依赖项,这些依赖项中又包含了更多的依赖项,导致整个文件夹的嵌套层级变得很深。

对于多包之间会存在公共依赖,如果对于每个依赖都生成自己独立的node_modules,那么就会对相同包重复安装多次,这就会占据很大的磁盘空间。且无限嵌套,也会超过windows的最大文件路径长度限制(265个字符)。

嵌套依赖项的模式是npm2中的一个特性,虽然可以保证依赖项的版本稳定性和精确性,但是它可能会导致嵌套层级变得很深,并占用大量的磁盘空间。

yarn

我们想到,既然树形结构存在弊端,为什么不将依赖包在根node_modules进行扁平化处理,这不就解决了依赖嵌套、依赖重复和路径限制问题了?

此时新方式yarn就横空诞生。

当使用yarn进行依赖管理时,我们可以看到所有依赖都会被安装在根目录下的node_modules文件夹中。与npm2不同的是,yarn采用了扁平依赖项的模式,这意味着相同的依赖包只会被安装一次,并且不会存在多个嵌套的node_modules文件夹。

使用yarn add koa进行安装,可以看到通过yarn进行管理的依赖全部平铺在根node_modules下,且没有重复依赖安装的问题。

但是,当某些依赖包存在多个版本时,yarn会将其中一个版本提升到根node_modules文件夹中,而其他依赖包则会继续维护自己的版本。这可能会导致某些依赖包无法正常工作,因为它们可能需要使用特定版本的依赖包。为了解决这个问题,yarn仍然需要使用嵌套的node_modules文件夹,以确保每个依赖包使用正确的版本。

值得注意的是,yarn采用的扁平依赖项模式具有许多优点,例如更快的安装速度,更少的磁盘空间占用和更少的依赖冲突问题。此外,yarn还提供了一个lock文件,该文件记录了所有依赖项的确切版本和位置,以确保依赖项的版本稳定性和一致性。

yarn的变与不变:

yarn采用了更加高效和可靠的依赖项管理方式,可以有效地避免依赖冲突和嵌套的问题。但是,对于某些多版本依赖包,yarn仍然需要使用node_modules嵌套的方式来确保每个依赖包都使用正确的版本。

npm3

npm3在2015年发布时引入了一种新的依赖项安装算法,称为“扁平依赖项”。其主要原理是通过将所有依赖项都放置在同一个目录下,并使用符号链接来实现依赖项的共享。

在npm3中,所有依赖项都被直接安装到根目录下的node_modules中,而不是像npm2一样在每个依赖包中嵌套一个node_modules目录。这种扁平化的结构可以减少依赖项的嵌套层级,从而降低了磁盘空间的占用和文件路径的长度。在这种模式下,所有依赖项都被安装到顶级node_modules文件夹中,这样就避免了嵌套依赖项的问题。这种模式虽然简单,但是它可能会导致依赖项的版本不稳定,从而可能会导致依赖冲突的问题。

当我们使用npm3安装koa包时,它会首先检查该包所需的所有依赖项是否已经安装,如果没有安装,则会将这些依赖项直接安装到根目录下的node_modules目录中。同时,npm3会使用符号链接将这些依赖项链接到需要使用它们的包的node_modules目录下。

通过使用符号链接,npm3可以实现依赖项的共享,从而避免了依赖项的重复安装和占用大量的磁盘空间。此外,npm3还支持npm shrinkwrap命令,可以生成一个lockfile文件,记录每个包所使用的依赖项的精确版本号,从而避免了版本冲突和不兼容的问题。

shrinkwrap 文件的作用是什么?

这个文件用于记录整个依赖树的结构和依赖包的版本信息,可以保证依赖包的版本稳定性和一致性。

那么使用扁平化方案就能完美解决以上问题吗?当然不是。

幽灵依赖:在声明中没有使用dependencies中的依赖,代码中也可以进行reqiure引入。没有在项目中进行显式依赖,如果别的包不再依赖这个包,就会导致代码因为依赖这个包,而没有进行安装,最终不能正常运行。磁盘浪费:对于依赖包只会提升一个,存在多个版本时其余包同样得进行拷贝到各自node_modules下,依然会存在磁盘空间浪费。

什么是幽灵依赖?

在安装和使用某个第三方包时,该包依赖的其他依赖没有在它的js文件中显式引入的情况。这些依赖可能在代码中被引用,但是没有被包含在软件包的package.json文件中。这种情况被称为“幽灵依赖”。

举个例子,假设有个项目需要依赖包 A 和 B,而这两个包都依赖于包 C,但是包 A 依赖于包 C 的版本 1.0.0,而包 B 依赖于包 C 的版本 2.0.0。在 npm2 中,这两个版本的包 C 会被分别安装在 A 和 B 的 node_modules 目录下,不会产生冲突。但在 npm3 中,这两个版本的包 C 可能会被安装在同一个 node_modules 目录下,这时候就会产生冲突,导致代码无法运行。

虽然在npm3提供了 npm dedupe 命令,可以是手动输入命令将重复的依赖项合并到顶层 node_modules 目录下,避免了幽灵依赖的问题。但是好像并没有很智能。

总的来说,npm3通过采用扁平化的依赖管理结构和符号链接机制,引入 shrinkwrap 文件实现了依赖项的共享和版本精确控制,并且减少了依赖项的嵌套层级和磁盘空间占用。可以手动使用 dedupe 命令等方式,解决了 npm2 中出现的幽灵依赖问题,提高了包管理的效率和可靠性。

pnpm

针对上面遗留下的两个问题,pnpm横空出世,采用硬链接和符号链接来管理依赖项,以减少重复下载和占用空间,从而有效地解决幽灵依赖和磁盘浪费的问题。

基于内容寻址的文件系统来存储磁盘的文件不会重复安装同一个包,只在磁盘中写入一次,而后在使用的地方通过hardlink同包不同版本,也尽可能复用代码

link:也就是软硬连接,这是操作系统提供的机制。

硬连接就是同一个文件的不同引用软链接是新建一个文件,文件内容指向另一个路径

具体来说,当使用 pnpm 安装koa包的依赖项时,它会首先检查系统上是否已经安装了所需的依赖项。如果已经安装,则 pnpm 将创建一个符号链接到该依赖项,而不是在当前项目中复制该依赖项。这样就避免了重复下载和占用磁盘空间的问题。

我们在命令行输入:

pnpm add koa

此外,pnpm 还支持不同的包引用方式,如路径引用和 git 仓库引用,这使得 pnpm 可以更快地安装依赖项并减少重复下载,从而提高开发效率和依赖项管理的可靠性。通过将包从全局 store 进行硬链接到项目的虚拟 store 中,pnpm 可以避免多次拷贝文件和深度嵌套路径过长的问题,从而进一步减少磁盘空间的占用和提高性能。

PNPM 的核心思想是在整个项目内共享依赖项,而不是每个项目都拥有自己的依赖项副本。

这是官方文档提供的原理图:

可以看到有个公共的依赖包安装池,然后通过软链接引入到各个项目所需要的依赖中,这样就减少了幽灵依赖、依赖嵌套和重复下载的问题。

PNPM的优点如下:

节省磁盘空间:pnpm采用链接的方式将依赖项共享到全局store中,避免了每个项目都需要拷贝一份依赖包的问题,从而显著减少了磁盘占用空间。

提升安装速度:pnpm不需要每次都下载相同的依赖项,而是从全局store中直接链接到各个项目中,因此可以极大地提高安装速度。

避免了幽灵依赖、重复依赖和依赖嵌套:pnpm采用链接的方式,避免了项目之间依赖相同包不一致的问题,同时避免了重复安装相同版本的依赖项和依赖嵌套的问题。

支持多种包引用方式:pnpm支持路径引用和git仓库引用,可以更加灵活地管理依赖项。

天生支持monorepo管理:得益于pnpm的软链接特性,可以在同一个workspace下共享依赖和模块等。

另外,对于存储大量依赖的情况,pnpm提供了「pnpm store prune」命令,可以定期清理不再使用的依赖项,释放磁盘空间。

参考文章关于现代包管理器的深度思考——为什么现在我更推荐 pnpm 而不是 npm/yarn?pnpm 是凭什么对 npm 和 yarn 降维打击的现代前端工程为什么越来越离不开 Monorepo?现代前端工程为什么越来越离不开 Monorepo?为什么越来越多的项目选择 Monorepo?pnpm官方文档写在最后

最后对不同包管理器的优缺点、特点做了一些总结:

学而知不足,水平有限,还望诸君多多指教。觉得文章不错的读者,不妨点个关注,收藏起来上班摸鱼的时候品尝。

关键词:

下一篇:
上一篇:

【环球速看料】关于包管理器Npm、Yarn和Pnpm的一些总结

天天视点!“南昌制造”加快拓展国际市场

世界观察:和平精英彩色字体怎么弄(和平精英彩色字体)

当前最新:适合送妈妈的花

通讯!崔振宽:寄情山水间 问道笔墨中

【全球热闻】穆里尼奥中计了,被人硬蹭流量,意大利艺术家又为老头画皇帝壁画

【全球新要闻】分析|森林狼若交易戈贝尔能换回什么?回报可能比你想象中还要少

动态焦点:天开实验室创新发展联盟成果展将亮相第七届世界智能大会

环球热点评!什么叫能写到墓志铭上的神操作?一发AWP灭5人,CSGO玩家一战封神

新消息丨最新!安庆东部新城再添住宅用地,位置在这→

每日快报!重磅!沈阳现代化都市圈博物馆联盟成立! 共计七城市31家博物馆!

环球新资讯:胆子真粗!两男子将涉黄小卡片发到警车上,网友:自投罗网

焦点快报!2022年 | 兆驰股份营收150.28亿,净利11.46亿,同比增长超244%!

【天天时快讯】飞机的简笔画图_飞机的简笔画

【世界时快讯】“夜经济”点燃城市烟火气 重庆民心佳园夜市出圈

前沿资讯!整治地下空间违规住人!北京住建委检查678处次普通地下室,未发现安全隐患

【世界独家】日本约146万人蛰居家中 成社会难题

每日速递:葵涌人大代表开展登山道建设议事活动,打造土洋红色线路

天天视点!泰国登革热确诊病例呈上升趋势

全球微资讯!OpenAI、微软、谷歌、苹果、英伟达等人工智能开发领域企业将制定标准:讨论会本周三举行

当前视点!2023年镍金属概念龙头股汇总(2023/4/11)

天天快播:什么是介入治疗_什么叫介入治疗

当前消息!四川新闻联播丨康定在浙江萧山推介优势资源

全球看点:合生和白发变黑发是真是假知乎(怎样白发变黑发)

当前速递!文旅部:规范旅游市场,打击“不合理低价游”

【全球快播报】广发证券(01776.HK):完成公开发行50亿元短期公司债券

每日聚焦:[快讯]龙迅股份公布2022年年度分红方案预案

快播:深圳市委党校局级干部培训班到光明区考察交流

焦点快播:评论:战巡+演习 解放军再现维护国家主权的决心与能力

当前速递!广州知识城集团5亿短期融资券将赎回本金及利息兑付 利率1.76%

天天讯息:守拙君_守拙

全球快播:派友圈|宁波小伙“特种兵”式旅游火了!你是哪种出游“流派”?说说你的旅行趣事

当前讯息:和讯个股快报:2023年04月10日 湖南裕能(301358)13:56分,股价快速拉升

环球滚动:缺蛋未解、猪肉价格又涨到天价 蓝营民代批陈吉仲早该下台

世界观速讯丨小米米家智能音频眼镜今天发布:轻至38.1g、众筹799元

环球热门:30多家金融机构和企业代表齐聚株洲高新区 只为这件事