【工具链】PNPM和NPM的区别

24 天前
15

【工具链】PNPM和NPM的区别

硬链接与软链接

1.什么是硬链接什么是软链接

硬链接:每一个硬链接文件实际上是同一个文件地址,直接指向文件系统的数据块(inode)进行访问,访问文件时其实是针对同一个inode进行操作。

软链接:相当于桌面快捷方式,是指向另一个文件或目录的路径引用,每个软链接文件实际上都有自己单独inode

软硬链接参考ref:https://juejin.cn/post/7056581097429139463

为什么不使用NPM

npm install 原理分析

npm 原理

npm 原理

扁平化

依赖树扁平化,解决的问题是,npm 3.0之前的版本会存在同一个依赖处于不同依赖层级树的时候,会被安装多次,树变扁平之后,同一个依赖只会安装一次。

如果说需要安装同一个依赖的不同版本,会判断已安装的依赖是否符合新依赖的版本范围(新版本的依赖是否兼容旧依赖版本),如果符合则跳过,不符合则在当前使用到新版依赖的模块的 node_modules 下安装该模块。

扁平化

扁平化

因此在模块中引用一个依赖包时,查找依赖的路径为:先从当前模块的node_module去寻找,找不到则去上一级模块的node_module进行查找,直至查找到全局路径的node_module为止

但是扁平化结构并没有改变,依赖冗余的问题,如果我们面临下面这种场景

不同版本的依赖及其子依赖

不同版本的依赖及其子依赖

npm install 的时候,按照 package.json 里依赖的顺序依次解析

如果先定义buffer则此时依赖结构为:

buffer的子依赖层级更高

buffer的子依赖层级更高

反之先定义buffer2,则:

buffer2的子依赖层级更高

buffer2的子依赖层级更高

也就是说即使是使用了依赖扁平化,npm只是解决了同一依赖同一版本的冗余重复问题,但npm依然没解决依赖新旧版本共存的问题,也还是会因为package.json中依赖顺序不同而导致新的问题,因此在npm5.0之后提出了package-lock.jsonpackage-lock.json 中已经缓存了每个包的具体版本和下载链接,不需要再去远程仓库进行查询,然后直接进入文件完整性校验环节,减少了大量网络请求。

缓存

在执行 npm installnpm update命令下载依赖后,除了将依赖包安装在node_modules 目录下外,还会在本地的缓存目录缓存一份。

通过 npm config get cache 命令可以查询到:在 LinuxMac 默认是用户主目录下的 .npm/_cacache 目录。

在这个目录下又存在两个目录:content-v2index-v5content-v2 目录用于存储 tar包的缓存,而index-v5目录用于存储tar包的 hash

npm 在执行安装时,可以根据 package-lock.json 中存储的 integrity、version、name 生成一个唯一的 key 对应到 index-v5 目录下的缓存记录,从而找到 tar包的 hash,然后根据 hash 再去找缓存的 tar包直接使用。

检验文件完整性

在下载依赖包之前,我们一般就能拿到 npm 对该依赖包计算的 hash 值,例如我们执行 npm info 命令,紧跟 tarball(下载链接) 的就是 shasum(hash)

用户下载依赖包到本地后,需要确定在下载过程中没有出现错误,所以在下载完成之后需要在本地在计算一次文件的 hash 值,如果两个 hash 值是相同的,则确保下载的依赖是完整的,如果不同,则进行重新下载

ref:https://cloud.tencent.com/developer/article/1555982

Yarn对比NPM3

  1. 更好的语义化: yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰

  2. 并行安装:npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。

  3. 版本统一:引入package-lock.json,进行版本统一管理

  4. 依赖缓存:从全局依赖缓存中复制所需要的文件存储到当前项目的node_module中

    The install process is broken down into three steps:

    1. Resolution: Yarn starts resolving dependencies by making requests to the registry and recursively looking up each dependency.
    2. Fetching: Next, Yarn looks in a global cache directory to see if the package needed has already been downloaded. If it hasn't, Yarn fetches the tarball for the package and places it in the global cache so it can work offline and won't need to download dependencies more than once. Dependencies can also be placed in source control as tarballs for full offline installs.
    3. Linking: Finally, Yarn links everything together by copying all the files needed from the global cache into the local node_modules directory.

ref:https://engineering.fb.com/2016/10/11/web/yarn-a-new-package-manager-for-javascript/

npm5做出的升级

1.依赖缓存:建立symlink 去软链接全局cache的中以内容寻址存储的文件,而不是直接copy 全局中node_modules(即非内容寻址存储模式)

2.引入yarn的package-lock.json

ref:https://blog.npmjs.org/post/161081169345/v500.html

不用Yarn的原因

Although it makes installations faster and it has some nice new features, it uses the same flat node_modules structure that npm does (since version 3).

即使yarn在npm3.0之前已经做了很多工作,但是npm5已经升级后,已经吸纳yarn这些的改进项,同时yarn本身并不能解决flat tree这种模式的硬伤问题。

ref:https://www.kochan.io/nodejs/why-should-we-use-pnpm.html

不用NPM的原因

Flat Tree这种设计本身就是有缺陷的:

  1. 模块可以访问它们没有依赖的包:在扁平化依赖树中,由于依赖包被提升到了项目根目录下的node_modules文件夹中,某些模块可能会意外访问到它们实际上并没有直接依赖的包。这可能导致模块间的耦合度增加,使得项目难以维护。
  2. 扁平化依赖树的算法相当复杂:为了将所有依赖尽可能地集中在顶层目录,需要一个复杂的算法来确定哪些包应该被提升,哪些应该保留在较低层次。这个过程需要处理版本冲突和依赖兼容性,是一个计算上和逻辑上都非常复杂的过程。
  3. 某些包必须被复制到一个项目的node_modules文件夹中:当不同的模块依赖同一个包但需要不同版本时,为了解决这种版本冲突,某些版本的包可能需要被复制多份存放在不同模块的node_modules目录下。这种情况虽然违背了扁平化的初衷,但有时是必需的,以确保每个模块都能正常工作。

And flattened dependency trees come with a bunch of issues:

  1. modules can access packages they don’t depend on
  2. the algorithm of flattening a dependency tree is pretty complex
  3. some of the packages have to be copied inside one project’s node_modules folder

Pnpm对比NPM和Yarn的优势

  1. 安全性:与Yarn类似,pnpm也使用一个特殊的文件记录所有已安装包的校验和(checksums)。这一机制可以在每个包的代码被执行前验证其完整性,从而保护项目免受损坏或恶意篡改的包的影响。
  2. 离线模式pnpm将所有下载的包文件(tarballs)保存在一个本地的注册表镜像中。这意味着如果本地已有所需的包,pnpm不会再发起网络请求。通过使用--offline参数,可以完全禁止HTTP请求,使得包管理工作完全在离线状态下进行,这对于没有网络连接或网络连接不稳定的环境非常有用。
  3. 速度pnpm不仅比npm更快,也比Yarn更快,无论是在冷缓存(之前未安装过任何包)还是热缓存(已经安装过某些包并缓存)的情况下。这一速度优势主要是因为Yarn是从缓存中复制文件,而pnpm则是直接从全局存储中链接文件。链接文件比复制文件更高效,因为它减少了数据的实际移动,节省了磁盘空间和时间。

pnpm has all the additional features that Yarn has over npm:

  1. security. Like Yarn, pnpm has a special file with all the installed packages’ checksums to verify the integrity of every installed package before its code is executed.
  2. offline mode. pnpm saves all the downloaded package tarballs in a local registry mirror. It never makes requests when a package is available locally. With the --offline parameter, HTTP requests can be prohibited at all.
  3. speed. pnpm is not only faster than npm, it is faster than Yarn. It is faster than Yarn both with cold and hot cache. Yarn copies files from cache whereas pnpm just links them from the global store.

PNPM的原理

pnpm的核心就是为了解决flat tree 的问题,于是pnpm对node_modules的处理显然与yarn和npm都不一样

pnpm的方式是:不使用逐级flat tree的方式,而是建立每个包和包中node_modules对应到当前项目root中node_modules的软链接,每个包都有直接特定的版本号后缀,然后软链接到独属于当前包的node_modules文件

pnpm原理

pnpm原理

ref:

https://pnpm.io/pnpm-vs-npm

https://www.kochan.io/nodejs/why-should-we-use-pnpm.html

https://www.kochan.io/nodejs/pnpms-strictness-helps-to-avoid-silly-bugs.html

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...