npm与pnpm包安装流程的差异对比

发表于 2024-06-04
更新于 2024-06-04
分类于 技术专栏
阅读量 88
字数统计 4074

这篇文章源于一道面试题:npm install的流程,包冲突怎么处理?pnpm有什么区别?

1、npm的安装

npm安装模式整体进行过两次大升级,如下,原先使用嵌套模式,但是会带来安装包的重复安装,浪费了很多硬盘空间,之后改成扁平模式,稍微解决了一些空间的浪费

  • 嵌套模式:
    • image.png
  • 扁平模式
    • image.png

1.1、实践一下

我在本地测试一下最新的npm版本(v8.12.1),新建了一个项目,引入testnpma包,和testnpmb包,二者共同依赖于testnpm包,但是依赖的版本不一样,testnpmb依赖的是testnpm包的2.0.0版本,testnpma依赖的是1.0.0版本。

image.png

安装之后生成的package-lock.json文件:

1{ 2 "name": "testnpmc", 3 "version": "1.0.0", 4 "lockfileVersion": 2, 5 "requires": true, 6 "packages": { 7 "": { 8 "name": "testnpmc", 9 "version": "1.0.0", 10 "license": "ISC", 11 "dependencies": { 12 "testnpma": "^1.0.0", 13 "testnpmb": "^1.0.0" 14 } 15 }, 16 "node_modules/testnpm": { 17 "version": "1.0.0", 18 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpm/-/testnpm-1.0.0.tgz", 19 "integrity": "sha512-zhyO/zUkqvGEgt4tuIQcACpMc9ZNiO/u/tUkcqOHQWaUD+H/Jz52gtlNrXUFz9IgrA9wVjOblys4KTQPsj/R5Q==", 20 "license": "ISC" 21 }, 22 "node_modules/testnpma": { 23 "version": "1.0.0", 24 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpma/-/testnpma-1.0.0.tgz", 25 "integrity": "sha512-t+HAnmWna6YlUPrkinmMvYNAl9SYr3WpBdrvIAFeMwdbp1YDVA7soYF7+qwpQBtd4jyGHs8HGANurzEFyMLKkg==", 26 "license": "ISC", 27 "dependencies": { 28 "testnpm": "^1.0.0" 29 } 30 }, 31 "node_modules/testnpmb": { 32 "version": "1.0.0", 33 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpmb/-/testnpmb-1.0.0.tgz", 34 "integrity": "sha512-pieeDuQ4JZaVBfQgkyvXEbjjN2kYek18MGpnxcccQXbcVvvf+AVMf+avj1VBkxo5jm7erfWN96ym0HVeHiAJKw==", 35 "license": "ISC", 36 "dependencies": { 37 "testnpm": "^2.0.0" 38 } 39 }, 40 "node_modules/testnpmb/node_modules/testnpm": { 41 "version": "2.0.0", 42 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpm/-/testnpm-2.0.0.tgz", 43 "integrity": "sha512-+GXGVhkN23cAoy9zLq+tTwqw1RviM18KNyOv0SVnciXbzAiNBDMztu6CIASsmGJ6impbWRWfq8zzhmJSPMtKlw==", 44 "license": "ISC" 45 } 46 }, 47 "dependencies": { 48 "testnpm": { 49 "version": "1.0.0", 50 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpm/-/testnpm-1.0.0.tgz", 51 "integrity": "sha512-zhyO/zUkqvGEgt4tuIQcACpMc9ZNiO/u/tUkcqOHQWaUD+H/Jz52gtlNrXUFz9IgrA9wVjOblys4KTQPsj/R5Q==" 52 }, 53 "testnpma": { 54 "version": "1.0.0", 55 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpma/-/testnpma-1.0.0.tgz", 56 "integrity": "sha512-t+HAnmWna6YlUPrkinmMvYNAl9SYr3WpBdrvIAFeMwdbp1YDVA7soYF7+qwpQBtd4jyGHs8HGANurzEFyMLKkg==", 57 "requires": { 58 "testnpm": "^1.0.0" 59 } 60 }, 61 "testnpmb": { 62 "version": "1.0.0", 63 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpmb/-/testnpmb-1.0.0.tgz", 64 "integrity": "sha512-pieeDuQ4JZaVBfQgkyvXEbjjN2kYek18MGpnxcccQXbcVvvf+AVMf+avj1VBkxo5jm7erfWN96ym0HVeHiAJKw==", 65 "requires": { 66 "testnpm": "^2.0.0" 67 }, 68 "dependencies": { 69 "testnpm": { 70 "version": "2.0.0", 71 "resolved": "http://192.168.3.110:8081/repository/npm-all/testnpm/-/testnpm-2.0.0.tgz", 72 "integrity": "sha512-+GXGVhkN23cAoy9zLq+tTwqw1RviM18KNyOv0SVnciXbzAiNBDMztu6CIASsmGJ6impbWRWfq8zzhmJSPMtKlw==" 73 } 74 } 75 } 76 } 77} 78

虽然硬盘空间浪费的问题得到了缓解,但同时这种扁平化的处理方式自身也存在许多问题,其中最为明显的问题就是”幽灵依赖“。

所谓的幽灵依赖是指我们明明没有在 package.json 的 dependencies 里声明某个依赖,但在代码里却可以 import 进来。原因很简单,因为项目依赖被铺平了,那么依赖的依赖自然也是可以被引入到项目中。

幽灵依赖带来的弊端很明显:我们显式依赖了A,A又依赖了B,这时候我们在项目中直接使用B是可以的,但如果某一天A不再依赖于B,那么我们项目中使用B的地方就会报错。

2、pnpm的安装

pnpm的安装模式完全颠覆了npm留下的大坑,借助于系统的软链接硬链接,以及.pnpm的扁平模式,彻底解决了上述的所有问题。

还是基于上述的项目结构,我可以看node_modules目录下的层次如下: image.png

也就是说,所有的依赖都是从全局 store 硬链接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依赖。

image.png

公众号关注一波~

微信公众号

关于评论和留言

如果对本文 npm与pnpm包安装流程的差异对比 的内容有疑问,请在下面的评论系统中留言,谢谢。

网站源码:linxiaowu66 · 豆米的博客

Follow:linxiaowu66 · Github