原包管理工具(npm、yarn)的痛点和pnpm

281 阅读2分钟

痛点:

npm2依赖不是扁平化的。所以出现了yarn和npm3,对包管理进行了扁平化,使得所有依赖的包都下载到同一级目录下。也就是说比如你安装一个 express,那么你会在 node_modules 下面只找到一个 express 的文件夹。而 express 依赖的项目都放在其文件夹下。

这个带来的问题或许 windows 用户深谙其痛,因为在这种安装环境下,会导致目录的层级特别高,而对于 windows 来说,最大的路径长度限制在 248 个字符,再加上 node_modules 这个单词又特别长。

扁平化后,存在的问题

1、幽灵依赖

“幽灵依赖” 指的是 项目中使用了一些 没有被定义在其 package.json 文件中 的 包。考虑下面的例子:

my-library/package.json

{
  "name": "my-library",
  "version": "1.0.0",
  "main": "lib/index.js",
  "dependencies": {
    "minimatch": "^3.0.4"
  },
  "devDependencies": {
    "rimraf": "^2.6.2"
  }
}
复制代码

但假设代码是这样:

my-library/lib/index.js

var minimatch = require("minimatch")
var expand = require("brace-expansion");  // ???
var glob = require("glob")  // ???

// (更多使用那些库的代码)

2、分身问题

node_modules
└─ demo-bar // v1.0.1
   ├─ index.js
   └─ package.json
└─ demo-baz
   ├─ index.js
   ├─ package.json
   └─ node_modules
      └─ demo-bar // v1.0.0
         ├─ index.js
         └─ package.json
└─ demo-foo
   ├─ index.js
   ├─ package.json
   └─ node_modules
      └─ demo-bar // v1.0.0
         ├─ index.js
         └─ package.json

同一台电脑多项目开发下载的包重复,每个项目都要下载相应的包,使得在电脑磁盘中占用内存大。

pnpm优点:速度快,节省磁盘空间。

pnpm原理:

硬链接和软链接

1.PNG

pnpm 首先将依赖安装到全局 store,然后通过 symbolic linkhard link 来组织目录结构,将全局的依赖链接到项目中,将项目的直接依赖链接到 node_modules 的顶层,所有的依赖则平铺于 node_modules/.pnpm 目录下,实现了所有项目的依赖共享 store 的全局依赖,解决了幽灵依赖和 NPM 分身的问题

在 pnpm 中,会将依赖安装到当前分区的 <home dir>/.pnpm-store 位置中,可以通过以下命令获得当前的 store 位置:

pnpm store path

然后利用 hard link 将所需的包从 node_modules/.pnpm 硬链接到 store 中,最后通过 symbolic linknode_modules 中的顶层依赖以及依赖的依赖符号链接到 node_modules/.pnpm 中。

由于require('xxx')只会向node_module中查找相关依赖,并不会向.pnpm查找,所以不会有幽灵依赖的问题。而node_module中的是软链接,链接之后的文件在.pnpm中,.pnpm中又是依赖的硬链接,然后就可以从磁盘中找到依赖的文件

1.PNG